cmus (2.12.0-2) unstable; urgency=medium
authorSebastian Ramacher <sramacher@debian.org>
Fri, 12 Sep 2025 21:00:35 +0000 (23:00 +0200)
committerSebastian Ramacher <sramacher@debian.org>
Fri, 12 Sep 2025 21:00:35 +0000 (23:00 +0200)
  * Team upload
  * Fix build with ffmpeg 8.0 (Closes: #1115013)

[dgit import unpatched cmus 2.12.0-2]

30 files changed:
1  2 
debian/changelog
debian/cmus.bash-completion
debian/cmus.install
debian/cmus.lintian-overrides
debian/control
debian/copyright
debian/docs
debian/examples
debian/gbp.conf
debian/patches/0001-atomic_ld.patch
debian/patches/0002-fix-blhc.patch
debian/patches/0003-ip-ffmpeg-more-precise-seeking.patch
debian/patches/0004-ip-ffmpeg-skip-samples-only-when-needed.patch
debian/patches/0005-ip-ffmpeg-remove-excessive-version-checks.patch
debian/patches/0006-ip-ffmpeg-major-refactor.patch
debian/patches/0007-Validate-sample-format-in-ip_open.patch
debian/patches/0008-ip-ffmpeg-flush-swresample-buffer-when-seeking.patch
debian/patches/0009-ip-ffmpeg-remember-swr_frame-s-capacity.patch
debian/patches/0010-ip-ffmpeg-reset-swr_frame_start-when-seeking.patch
debian/patches/0011-ip-ffmpeg-better-frame-skipping-logic.patch
debian/patches/0012-ip-ffmpeg-don-t-process-empty-frames.patch
debian/patches/0013-ip-ffmpeg-improve-readability.patch
debian/patches/0014-ip-ffmpeg-fix-building-for-ffmpeg-8.0.patch
debian/patches/0015-ip-ffmpeg-change-sample-format-conversions.patch
debian/patches/series
debian/rules
debian/salsa-ci.yml
debian/source/format
debian/upstream/metadata
debian/watch

index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..38283a528801e5bd75cff03720e563400f158775
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,598 @@@
++cmus (2.12.0-2) unstable; urgency=medium
++
++  * Team upload
++  * Fix build with ffmpeg 8.0 (Closes: #1115013)
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Fri, 12 Sep 2025 23:00:35 +0200
++
++cmus (2.12.0-1) unstable; urgency=medium
++
++  * Team upload.
++
++  [ Philippe SWARTVAGHER ]
++  * New upstream version 2.12.0 (Closes: #1087737)
++    + Refresh patches
++  * Bump standards-version to 4.7.2: no change needed
++  * d/rules: remove as-needed linker flag
++  * Add lintian override for library-not-linked-against-libc
++    of usr/lib/cmus/op/sndio.so
++  * Add patch to use hardening flags to build Doc/ttman
++
++  [ Helmut Grohne ]
++  * Fix FTCBFS: Fix build/host confusion. (Closes: #954749)
++
++  [ Dylan Aïssi ]
++  * Convert debian/copyright to DEP5
++
++ -- Philippe SWARTVAGHER <phil.swart@gmx.fr>  Sat, 15 Mar 2025 22:56:48 +0100
++
++cmus (2.11.0-1) unstable; urgency=medium
++
++  * Team upload
++  * New upstream version 2.11.0
++    - Fix build with ffmpeg 7.0 (Closes: #1072405)
++  * debian/patches: Refresh patches
++  * debian/control:
++    - Bump Standards-Version
++    - Use pkgconf
++    - Use openmpt's modplug
++    - Use libncurses-dev
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Sun, 09 Jun 2024 23:45:17 +0200
++
++cmus (2.10.0-4) unstable; urgency=medium
++
++  * Team upload
++  * debian/patches: Apply upstream patch to fix compatibility with ffmpeg 6.0
++    (Closes: #1041375)
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Thu, 27 Jul 2023 21:00:31 +0200
++
++cmus (2.10.0-3) unstable; urgency=medium
++
++  * Team upload
++  * debian/control: Bump Standards-Version
++  * debian/: Remove roar support (Closes: #1030661)
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Tue, 07 Feb 2023 09:20:50 +0100
++
++cmus (2.10.0-2) unstable; urgency=medium
++
++  * Team upload
++  * Add a patch from upstream to fix a freeze when exiting cmus
++
++ -- Philippe SWARTVAGHER <phil.swart@gmx.fr>  Sun, 31 Jul 2022 22:01:04 +0200
++
++cmus (2.10.0-1) unstable; urgency=medium
++
++  * Team upload
++
++  [ Jenkins ]
++  * Remove constraints unnecessary since buster
++
++  [ Philippe SWARTVAGHER ]
++  * New upstream version 2.10.0
++  * Bump d/watch version
++  * Bump standards-version to 4.6.1
++  * Add a patch to fix a typo spotted by Lintian
++
++ -- Philippe SWARTVAGHER <phil.swart@gmx.fr>  Wed, 13 Jul 2022 20:40:37 +0200
++
++cmus (2.9.1-1) unstable; urgency=medium
++
++  * Team upload
++  * New upstream release
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Fri, 22 Jan 2021 22:28:04 +0100
++
++cmus (2.9.0-1) unstable; urgency=medium
++
++  * Team upload
++
++  [ Debian Janitor ]
++  * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository,
++    Repository-Browse.
++
++  [ Patrick Gaskin ]
++  * Fix missing dependency for MPRIS support
++
++  [ Sebastian Ramacher ]
++  * New upstream release
++  * debian/control:
++    - Bump Standards-Version
++    - Bump debhelper compat to 13
++    - Set RRR: no
++  * debian/patches/12-typos.patch: Removed, fixed upstream
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Tue, 19 Jan 2021 20:15:26 +0100
++
++cmus (2.8.0-2) unstable; urgency=medium
++
++  * Set build flags via /usr/share/dpkg/buildflags.mk
++  * Link with -latomic to fix FTBFS on various architectures (Closes: #935678)
++
++ -- Ryan Kavanagh <rak@debian.org>  Sat, 07 Sep 2019 10:37:13 -0400
++
++cmus (2.8.0-1) unstable; urgency=medium
++
++  [ Ondřej Nový ]
++  * Use debhelper-compat instead of debian/compat
++
++  [ Helmut Grohne ]
++  * Fix FTCBFS: Supply a cross environment to ./configure. (Closes: #911163)
++
++  [ Ryan Kavanagh ]
++  * New upstream version 2.8.0 (Closes: #932107, #783498)
++    + Update copyright file with new holders
++    + Drop 12-ffmpeg-4.0.patch (applied upstream)
++    + Refresh patches
++  * Drop outdated get-orig-source target from rules
++  * Fix typos in source, 12-typos.patch
++  * Enable hardening
++  * Bump debphelper compat to 12
++  * Bump standards-version to 4.4.0
++  * cmus-plugin-ffmpeg (<< 2.8.0) breaks cmus (>= 2.8.0)
++
++ -- Ryan Kavanagh <rak@debian.org>  Sat, 17 Aug 2019 14:51:27 -0400
++
++cmus (2.7.1+git20160225-2) unstable; urgency=medium
++
++  * Team upload.
++
++  [ James Cowgill ]
++  * Add upstream patch to fix FTBFS with FFmpeg 4.0. (Closes: #888384)
++  * d/changelog: Remove trailing blank line.
++
++  [ Alessio Treglia ]
++  * Remove myself from the Uploaders field.
++
++  [ Ondřej Nový ]
++  * d/control: Set Vcs-* to salsa.debian.org.
++  * d/changelog: Remove trailing whitespaces.
++
++  [ Felipe Sateler ]
++  * Change maintainer address to debian-multimedia@lists.debian.org.
++
++ -- James Cowgill <jcowgill@debian.org>  Thu, 17 May 2018 11:34:35 +0100
++
++cmus (2.7.1+git20160225-1) unstable; urgency=medium
++
++  * Team upload.
++  * New upstream snapshot.
++    - Fix build against ffmpeg 3.0. (Closes: #810557)
++  * debian/patches/{01_config.mk.diff,02_link_avcodec.patch}: Removed, applied
++    upstream.
++  * debian/control:
++    - Bump Standards Version.
++    - Update Vcs-Git.
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Sun, 06 Mar 2016 21:37:57 +0100
++
++cmus (2.7.1-1) unstable; urgency=medium
++
++  * Team upload.
++
++  [ Alessio Treglia ]
++  * Demote extra plugins to Suggests (Closes: #789256)
++  * Refresh patchset for 2.6.0.
++
++  [ Sebastian Ramacher ]
++  * New upstream release. (Closes: #779335, #792134)
++    - Use libswresample instead of libavresample. (Closes: #805169, #805109)
++  * Update path for README
++  * debian/control:
++    - Add libdiscid-dev, libopusfile-dev, libsamplerate0-dev and libjack-dev
++      to Build-Depends.
++    - Change libavresample-dev to libswresample-dev in Build-Depends and add
++      libavcodec-dev.
++    - Add bash-completion to Build-Depends.
++    - Bump Standards-Version to 3.9.6.
++    - Update Vcs-Browser.
++    - Make cmus-plugin-ffmpeg depend on the same version of cmus (Closes:
++      #695072)
++  * debian/cmus.install: Install zsh completion.
++  * debian/cmus.bash-completion: Install bash completion.
++  * debian/rules:
++    - Build with --parallel and --with bash-completion.
++    - Handle jack shlibs similar to pulse.
++  * debian/patches:
++    - libav10.patch: Removed, no longer needed.
++    - 02_link_avcodec.patch: Functions from libavcodec are used so make sure
++      the ffmpeg plugin is linked against libavcodec.
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Sun, 15 Nov 2015 19:24:52 +0100
++
++cmus (2.5.0-7) unstable; urgency=medium
++
++  * Re-introduce Roaraudio support (Closes: #680745):
++    - debian/control: Add build-dependency on libroad-dev.
++    - debian/rules: Tune dpkg-shlibdeps call to move pulse and roar's
++      dependencies to Recommends. Made the whole mechanism slightly more
++      elegant.
++  * Enable CUE support.
++  * The project has moved to github, update the Homepage field accordingly.
++  * Update debian/watch, project has moved from sourceforge to github.
++
++ -- Alessio Treglia <alessio@debian.org>  Thu, 14 Aug 2014 13:45:10 +0100
++
++cmus (2.5.0-6) unstable; urgency=medium
++
++  * Team upload.
++  * Upload to unstable.
++
++ -- Sebastian Ramacher <sramacher@debian.org>  Sun, 11 May 2014 23:45:16 +0200
++
++cmus (2.5.0-5) experimental; urgency=low
++
++  * Team upload.
++  * Compile against libav10 (Closes: #739301)
++  * Bump standards version
++
++ -- Reinhard Tartler <siretart@tauware.de>  Mon, 24 Mar 2014 19:35:28 -0400
++
++cmus (2.5.0-4) unstable; urgency=low
++
++  [ Ryan Kavanagh ]
++  * Patches were applied upstream
++
++  [ Alessio Treglia ]
++  * Add patch to prevent FTBFS. (Closes: #724181)
++
++ -- Alessio Treglia <alessio@debian.org>  Sun, 06 Oct 2013 20:46:25 +0100
++
++cmus (2.5.0-3) unstable; urgency=low
++
++  * Don't FTBFS due to missing config.mk (Closes: #720781), 01_config.mk.diff
++  * Fix typo in cmus binary, 02_fix_typo.diff
++  * Enable build hardening
++    + Bump debhelper version to 9.0.0 and compat to 9
++    + Introduce 03_cppflags.diff to use CPPFLAGS; needed for function
++      fortification
++    + Override hardening-no-fortify-functions false positives
++  * Bump standards version to 3.9.4
++  * Switch to canonical Vcs-* fields
++  * Enable verbose build logs
++
++ -- Ryan Kavanagh <rak@debian.org>  Thu, 29 Aug 2013 13:48:30 -0400
++
++cmus (2.5.0-2) unstable; urgency=low
++
++  * Upload to unstable.
++
++ -- Alessio Treglia <alessio@debian.org>  Sat, 11 May 2013 01:21:18 +0200
++
++cmus (2.5.0-1) experimental; urgency=low
++
++  * New upstream release:
++    - CUE sheets support.
++    - cdio input plugin.
++    - support for WavPack `.wvc` correction files.
++    - new «zenburn» color scheme and text attributes (bold/reverse/...)
++      support for UI elements.
++    - improved tab completion, new scroll_offset and icecast_default_charset
++      options, even better tag parsing and compilations handling, and
++      numerous small enhancements all over the place.
++  * Build-depend on libcddb2-dev,libcdio-cdda-dev.
++
++ -- Alessio Treglia <alessio@debian.org>  Thu, 15 Nov 2012 00:28:20 +0000
++
++cmus (2.4.3-2) unstable; urgency=low
++
++  [ Ryan Kavanagh ]
++  * Update my email address to @debian.org
++  * Drop DM-Upload-Allowed: yes, no longer needed
++
++  [ Alessio Treglia ]
++  * Build cmus without roar support. (Closes: #675610)
++  * Bump Standards.
++
++ -- Alessio Treglia <alessio@debian.org>  Sat, 02 Jun 2012 20:07:57 +0200
++
++cmus (2.4.3-1) unstable; urgency=low
++
++  * New upstream release.
++
++ -- Alessio Treglia <alessio@debian.org>  Sat, 03 Dec 2011 12:55:46 +0100
++
++cmus (2.4.2-1) unstable; urgency=low
++
++  * New upstream release.
++  * Drop 0001-fix-compile-error-for-new-versions-of-ffmpeg.patch,
++    applied upstream.
++
++ -- Alessio Treglia <alessio@debian.org>  Tue, 26 Jul 2011 10:13:25 +0200
++
++cmus (2.4.1-2) unstable; urgency=low
++
++  * Add Ubuntu-specific patch to fix FTBFS with newest version of ffmpeg.
++  * Replace negated list of architectures with linux-any (Closes: #634706).
++
++ -- Alessio Treglia <alessio@debian.org>  Sat, 23 Jul 2011 10:48:29 +0200
++
++cmus (2.4.1-1) unstable; urgency=medium
++
++  * New upstream release (Closes: #628422):
++    - Doc: add help for :shell
++    - ffmpeg: move up "config/ffmpeg.h" include
++    - fix two memleaks
++    - fix cache refresh bug
++    - configure: fix FLAC include path
++    - configure: fix ffmpeg header detection
++    - fix TCP/IP networking protocol
++    - fix segfault when hitting win-activate on empty tree
++    - display error if seeking failed
++    - fix segfault when using tqueue/lqueue
++    - fix lqueue command
++    - fix infinite loop when adding certain mp3 files
++    - fix reading of id3v2 tags at the end of files
++    - more fault-tolerant integer tag-reading
++  * Bump urgency to medium as the previous release was seriously buggy.
++
++ -- Alessio Treglia <alessio@debian.org>  Sun, 29 May 2011 19:18:48 +0200
++
++cmus (2.4.0-1) unstable; urgency=low
++
++  * New upstream release "Easter egg":
++    - Mutt-like short filters.
++    - Live filtering.
++    - Resume support.
++    - Smarter string handling.
++    - Long format options, including ones for bitrate/codec.
++    - HTTP proxy support for streams via http_proxy environment variable.
++    - Less CPU wakeups during playback.
++    - New RoarAudio output plugin.
++    - Support for big-endian systems, lots of different audio sample formats,
++      almost any C compiler and unix-like OS out there.
++    - Various bugfixes.
++    - Full release notes are available at:
++      http://sourceforge.net/mailarchive/message.php?msg_id=27403242
++  * debian/watch: Properly handle release-candidate,beta releases.
++  * Remove debian/patches directory, all patches have been applied upstream.
++  * Bump Standards.
++
++ -- Alessio Treglia <alessio@debian.org>  Tue, 26 Apr 2011 23:30:07 +0200
++
++cmus (2.3.5-1) unstable; urgency=low
++
++  * New upstream release:
++    - Features gapless MP3 playback.
++    - Native PulseAudio support.
++    - Faster startup.
++    - Improve buildsystem.
++  * Refresh patches.
++  * Remo 21-missing_plugins.patch, applied upstream.
++
++ -- Alessio Treglia <alessio@debian.org>  Sat, 23 Apr 2011 09:56:57 +0200
++
++cmus (2.3.4-3) unstable; urgency=low
++
++  * Handle missing dependencies more gracefully:
++    - cmus silently skips plugins with missing dependencies, and instead
++      outputs a debug message. Original patch by Johannes Weißl, already
++      accepted upstream.
++
++ -- Alessio Treglia <alessio@debian.org>  Fri, 01 Apr 2011 08:59:01 +0200
++
++cmus (2.3.4-2) unstable; urgency=low
++
++  * Avoid to depend on several sound servers (Closes: #612887) and let
++    users choose to rely on the favorite one.
++    - debian/control:
++      + Add shlibs:Recommends field.
++    - debian/rules:
++      + Supply {dh_,dpkg-}shlibdeps with proper options to demote roar
++        and pulse audio dependencies to Recommends.
++
++ -- Alessio Treglia <alessio@debian.org>  Tue, 15 Mar 2011 12:46:03 +0100
++
++cmus (2.3.4-1) unstable; urgency=low
++
++  [ Ryan Kavanagh ]
++  * New upstream release.
++  * Dropped 01_spelling_mistakes.diff, 02_cmus-tutorial_whatis.diff
++    and 03-terminal_corruption.patch (applied upstream).
++  * Refreshed 10-roaraudio_support.patch
++  * Bump my copyright
++
++  [ Alessio Treglia ]
++  * Add DM-Upload-Allowed: yes.
++
++ -- Ryan Kavanagh <ryanakca@kubuntu.org>  Tue, 22 Feb 2011 09:03:23 -0500
++
++cmus (2.3.3-4) unstable; urgency=low
++
++  * Upload to unstable.
++
++ -- Alessio Treglia <alessio@debian.org>  Wed, 09 Feb 2011 12:05:49 +0100
++
++cmus (2.3.3-3) experimental; urgency=low
++
++  * Add RoarOutput plugin (Closes: #609202), thanks to
++    Philipp Schafft <lion@lion.leolix.org> for the patch.
++  * Add patch taken from upstream's git to fix segfault when adding to
++    queue.
++  * Build-depends on libroar-dev (>= 0.4~beta2).
++
++ -- Alessio Treglia <alessio@debian.org>  Mon, 17 Jan 2011 02:23:04 +0100
++
++cmus (2.3.3-2) unstable; urgency=low
++
++  * Prevent terminal corruption on track change.
++  * debian/copyright: Update sources download location.
++  * Split cmus to provide smart dependencies (Closes: #442423).
++  * Bump Standards.
++
++ -- Alessio Treglia <alessio@debian.org>  Sun, 01 Aug 2010 12:26:08 +0200
++
++cmus (2.3.3-1) unstable; urgency=low
++
++  [ Ryan Kavanagh ]
++  * New upstream release (Closes: #572284)
++  * Imported Upstream version 2.3.3
++  * Changed to source format 3.0 source. Involved converting
++    dpatch->quilt and dropping dpatch B-D.
++  * Dropped 01_cmusffmpeg.diff, no longer needed. Upstream checks for
++    ffmpeg and falls back to libavcodec for us.
++  * Dropped 02_cmusstatusdisplay.diff, included upstream.
++  * Dropped Yavor's mpcdec patch. Upstream expanded on it, using his
++    code if building under MPC SV8, the old code otherwise.
++  * Updated debian/watch
++  * Updated copyright file with new copyright holders and download
++    location.
++  * This is a new upload, package will thus be rebuilt against libavformat.
++    (Closes: #568361).
++  * Dropped debian/patches directory
++  * Move to debhelper 7 rules
++  * Now standards-version 3.8.4
++  * Fix debhelper-but-no-misc-depends lintian warning
++  * Override dh_auto_configure because upstream uses a homebrewed configure
++    script that doesn't accept --a=b style options
++  * Bump debhelper version to (>= 7.0.50~) because we're using override_dh_*
++  * Fix spelling mistakes in binary and documentation
++    (01_spelling_mistake.diff)
++  * Fix whatis entry for cmus-tutorial manpage (02_cmus-tutorial_whatis.diff)
++  * Added Julien Louis' and my own packaging copyright blurb to
++    debian/copyright.
++
++  [ Alessio Treglia ]
++  * This isn't a non-maintainer upload, we adopt this (Closes: #587604).
++  * Add debian/gbp.conf file.
++  * debian/control:
++    - Add Vcs-* tags.
++    - Bump Standards.
++    - Lines should be shorter than 80 characters.
++    - Add myself to Uploaders field, I'll take care of sponsoring this in
++      future.
++    - Build-depend on pkg-config.
++    - Drop unnecessary Recommends field.
++  * Drop aRTs support as it is no longer maintained.
++  * Add PulseAudio support.
++  * debian/rules:
++    - Call configure script instead of relying on dh_auto_configure.
++  * Drop README.source, we don't rely on dpatch as patch system.
++  * Update debian/copyright.
++
++ -- Alessio Treglia <alessio@debian.org>  Sun, 04 Jul 2010 20:06:58 +0200
++
++cmus (2.2.0-4.1) unstable; urgency=low
++
++  * NMU
++  * Patch from Yavor Doganov to port cmus to the new mpcdec API,
++    thereby allowing cmus to build from source again.
++    closes: #476382, #552820.
++
++ -- Clint Adams <schizo@debian.org>  Sun, 31 Jan 2010 00:03:40 -0500
++
++cmus (2.2.0-4) unstable; urgency=low
++
++  * Updated debian/watch file Closes: #449897
++    - Thanks to Raphael Geissert <atomo64@gmail.com>
++  * Fix the ffmpeg/avcodec.h includes Closes: #517570
++    - Thanks to Cyril Brulebois <kibi@debian.org>
++  * Added Recommends libasound2, libartsc0, libao2 Closes: #439719
++  * Added Depends line in debian/control
++  * Added dpatch on Build-Depends on debian/control
++  * Deleted commented lines on debian/rules
++  * Update debian/rules for dpatch dependence
++  * Changed debian/control
++    - Standard-Version to 3.8.1 ( was 3.8.0 )
++    - Added debian/README.source
++    - Updated to debhelper to 7
++    - Updated debian/compat (was 5)
++    - Added Homepage field
++
++ -- Carlos Eduardo Sotelo Pinto (krlos) <krlos.aqp@gmail.com>  Thu, 19 Mar 2009 13:38:16 -0500
++
++cmus (2.2.0-3) unstable; urgency=low
++
++  * Acknowledging NMU.  Closes: #509277.
++
++ -- Carlos Eduardo Sotelo Pinto (krlos) <krlos.aqp@gmail.com>  Mon, 29 Dec 2008 22:01:01 +0100
++
++cmus (2.2.0-2) unstable; urgency=low
++
++  * New maintainer. Closes: #484734
++  * Changed debian/control
++    - Standard-Version to 3.8.0 ( was 3.7.2 no changes needed )
++
++ -- Carlos Eduardo Sotelo Pinto (krlos) <krlos.aqp@gmail.com>  Wed, 03 Sep 2008 17:46:50 -0500
++
++cmus (2.2.0-1.1) unstable; urgency=high
++
++  * Non-maintainer upload by the Security Team.
++  * Modify example script cmus-status-display to write the current
++    status to .cmus-status in the user's home instead of /tmp/cmus-status,
++    since the latter could lead to symlink attacks. CVE-2008-5375
++    (Closes: #509277)
++
++ -- Moritz Muehlenhoff <jmm@debian.org>  Sun, 28 Dec 2008 14:57:06 +0100
++
++cmus (2.2.0-1) unstable; urgency=low
++
++  * New upstream release
++  * Add libwavpack-dev and libavformat.dev to Build-Depends
++  * Update debian/copyright
++
++ -- Julien Louis <ptitlouis@sysif.net>  Fri, 27 Jul 2007 21:54:36 +0200
++
++cmus (2.1.0-2) unstable; urgency=low
++
++  * Rebuild against libflac8 (Closes: #426638).
++
++ -- Julien Louis <ptitlouis@sysif.net>  Mon, 04 Jun 2007 22:56:58 +0200
++
++cmus (2.1.0-1) unstable; urgency=low
++
++  * New upstream release (closes: #399965).
++  * Updated debian/copyright
++  * Added libfaad-dev to Build-Depends
++
++ -- Julien Louis <ptitlouis@sysif.net>  Thu, 21 Dec 2006 20:25:59 +0100
++
++cmus (2.0.4-1) unstable; urgency=low
++
++  * New upstream release.
++  * Added debian/watch file.
++  * Build-Depends agains libasound2-dev (>= 1.0.11).
++
++ -- Julien Louis <ptitlouis@sysif.net>  Wed, 23 Aug 2006 03:34:04 +0200
++
++cmus (2.0.3-3) unstable; urgency=low
++
++  * Drop libasound2-dev Build Dependency on non-linux arches
++    (Closes: #377885).
++
++ -- Julien Louis <ptitlouis@sysif.net>  Wed, 12 Jul 2006 01:06:02 +0200
++
++cmus (2.0.3-2) unstable; urgency=low
++
++  * Move all dh_* helper stuff in the binary-arch target (Closes: #376320).
++  * Remove debian/patches/01_asciidoc_xsl_path.dpatch since it is not usefull.
++  * Remove dpatch from Build-Depends.
++
++ -- Julien Louis <ptitlouis@sysif.net>  Sun,  2 Jul 2006 14:16:03 +0200
++
++cmus (2.0.3-1) unstable; urgency=low
++
++  * New upstream release.
++  * Remove asciidoc, docbook-xsl, doxbook-xml ans xsltproc from Build-Depends.
++  * Add libartsc0-dev and libao-dev to Build-Depends.
++
++ -- Julien Louis <ptitlouis@sysif.net>  Sun, 18 Jun 2006 17:26:44 +0200
++
++cmus (2.0.2-1) unstable; urgency=low
++
++  * New upstream release.
++  * Remove ASCIIDOC patch since upstream now search for
++    /etc/asciidoc/docbook-xsl/.
++  * Add docbook-xml to Build-Depends.
++  * Bump Standards-Version no change needed.
++  * Added REAMDE.Debian
++
++ -- Julien Louis <ptitlouis@sysif.net>  Tue, 30 May 2006 22:12:01 +0200
++
++cmus (2.0.0-1) unstable; urgency=low
++
++  * Initial release (Closes: #340000)
++
++ -- Julien Louis <ptitlouis@sysif.net>  Mon,  7 Nov 2005 18:19:55 +0100
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ca9c5f284eb4ab85c2df00eb3fdc7340affb6281
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++contrib/cmus.bash-completion cmus
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cb199e14e836ea035c91d1b89d5273d2fa9464cf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2 @@@
++usr
++contrib/_cmus usr/share/zsh/vendor-completions
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4ccc1280f4560c3b68040012e2c80a785537768d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++cmus: hardening-no-fortify-functions usr/lib/cmus/ip/flac.so
++
++## This library actually doesn't directly call any libc function
++cmus: library-not-linked-against-libc [usr/lib/cmus/op/sndio.so]
diff --cc debian/control
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d33178eafa4a6ab01ecb336a8fcfd98a0084c82a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,77 @@@
++Source: cmus
++Section: sound
++Priority: optional
++Maintainer: Debian Multimedia Maintainers <debian-multimedia@lists.debian.org>
++Uploaders:
++ Ryan Kavanagh <rak@debian.org>
++Build-Depends:
++ debhelper-compat (= 13),
++ bash-completion,
++ libao-dev,
++ libasound2-dev [linux-any],
++ libavcodec-dev,
++ libavformat-dev,
++ libswresample-dev,
++ libcddb2-dev,
++ libcdio-cdda-dev,
++ libcue-dev,
++ libdiscid-dev,
++ libfaad-dev,
++ libflac-dev,
++ libjack-dev,
++ libmad0-dev,
++ libmpcdec-dev,
++ libncurses-dev,
++ libopenmpt-modplug-dev,
++ libopusfile-dev,
++ libpulse-dev,
++ libsamplerate0-dev,
++ libsystemd-dev,
++ libvorbis-dev,
++ libwavpack-dev,
++ pkgconf
++Standards-Version: 4.7.2
++Homepage: https://cmus.github.io/
++Vcs-Git: https://salsa.debian.org/multimedia-team/cmus.git
++Vcs-Browser: https://salsa.debian.org/multimedia-team/cmus
++Rules-Requires-Root: no
++
++Package: cmus
++Architecture: any
++Depends:
++ ${misc:Depends},
++ ${shlibs:Depends}
++Recommends:
++ cmus-plugin-ffmpeg
++Suggests:
++ ${shlibs:Suggests}
++Breaks: cmus-plugin-ffmpeg (<< 2.8.0)
++Description: lightweight ncurses audio player
++ C* Music Player is a modular and very configurable ncurses-based audio player.
++ It has some interesting features like configurable colorscheme, mp3 and ogg
++ streaming, it can be controlled with an UNIX socket, filters, album/artists
++ sorting and a vi-like configuration interface.
++ .
++ It currently supports different input formats:
++  - Ogg Vorbis
++  - MP3 (with libmad)
++  - FLAC
++  - Wav
++  - Modules (with libmodplug)
++  - Musepack
++  - AAC
++  - Windows Media Audio
++
++Package: cmus-plugin-ffmpeg
++Architecture: any
++Depends:
++ ${misc:Depends},
++ ${shlibs:Depends},
++ cmus (= ${binary:Version})
++Description: lightweight ncurses audio player (FFmpeg plugin)
++ C* Music Player is a modular and very configurable ncurses-based audio player.
++ It has some interesting features like configurable colorscheme, mp3 and ogg
++ streaming, it can be controlled with an UNIX socket, filters, album/artists
++ sorting and a vi-like configuration interface.
++ .
++ This package adds FFmpeg support to C* Music Player.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..01793b01c40da113201d0a137a9e67334dbd2369
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,38 @@@
++Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
++Source: https://github.com/cmus/cmus
++
++Files: *
++Copyright: 2004-2007 Timo Hirvonen <tihirvon@gmail.com>
++           2009 Gregory Petrosyan <gregory.petrosyan@gmail.com>
++           1999 Paul N. Fisher <rao@gnu.org>
++           2002 Andy Lo A Foe <andy@alsaplayer.org>
++           2006 dnk <dnk@bjum.net>
++           2006 Chun-Yu Shei <cshei AT cs.indiana.edu>
++           2007 Kevin Ko <kevin.s.ko@gmail.com>
++           2007 dnk <dnk@bjum.net>
++           2007 Johannes Weißl
++           2016 Nic Soudée
++License: GPL-2+
++
++Files: debian/*
++Copyright: 2005-2008 Julien Louis <ptitlouis@sysif.net>
++           2010-2019 Ryan Kavanagh <ryanakca@kubuntu.org>
++           2010 Alessio Treglia <alessio@debian.org>
++License: GPL-2+
++
++License: GPL-2+
++ This package is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++ .
++ This package is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ GNU General Public License for more details.
++ .
++ You should have received a copy of the GNU General Public License
++ along with this program.  If not, see <https://www.gnu.org/licenses/>.
++ .
++ On Debian systems, the full text of the GNU General Public License
++ version 2 can be found in `/usr/share/common-licenses/GPL-2'.
diff --cc debian/docs
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..93c309db748b9dee1025b2f2dd711bf49b46aa05
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2 @@@
++README.md
++contrib/
diff --cc debian/examples
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5a8a7b54559efe45c3fd57872f9268dac8dbcf96
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++cmus-status-display
diff --cc debian/gbp.conf
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cec628c7444886870d72dc8bcd536479e7f8a284
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2 @@@
++[DEFAULT]
++pristine-tar = True
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0ecab21fd9e4c04c548b607d9afc745e7f3f3d06
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,30 @@@
++From: Ryan Kavanagh <rak@debian.org>
++Date: Thu, 27 Jul 2023 20:59:47 +0200
++Subject: Pass LDLIBS to the linker
++
++Origin: Debian
++Bug-Debian: http://bugs.debian.org/935678
++Forwarded: no
++Reviewed-by: Ryan Kavanagh <rak@debian.org>
++Last-Update: 2019-09-07
++
++Needed to pass -latomic at the end so that we can fix a FTBFS on various
++architectures.
++Last-Update: 2019-09-07
++---
++ Makefile | 2 +-
++ 1 file changed, 1 insertion(+), 1 deletion(-)
++
++diff --git a/Makefile b/Makefile
++index 76a4d59..720f043 100644
++--- a/Makefile
+++++ b/Makefile
++@@ -19,7 +19,7 @@ include scripts/lib.mk
++ CFLAGS += -D_FILE_OFFSET_BITS=64
++ 
++ CMUS_LIBS = $(PTHREAD_LIBS) $(NCURSES_LIBS) $(ICONV_LIBS) $(DL_LIBS) $(DISCID_LIBS) \
++-                     -lm $(COMPAT_LIBS) $(LIBSYSTEMD_LIBS)
+++                     -lm $(COMPAT_LIBS) $(LIBSYSTEMD_LIBS) $(LDLIBS)
++ 
++ command_mode.o input.o main.o ui_curses.o op/pulse.lo: .version
++ command_mode.o input.o main.o ui_curses.o op/pulse.lo: CFLAGS += -DVERSION=\"$(VERSION)\"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..95dac1f6ed465f68f53ad76ca41ff69eeb40fb80
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,22 @@@
++Description: Use hardening flags for Doc/ttman
++Author: Philippe SWARTVAGHER <phil.swart@gmx.fr>
++Forwarded: not-needed
++Last-Update: 2025-03-16
++---
++diff --git a/Makefile b/Makefile
++index 76a4d59..3860f77 100644
++--- a/Makefile
+++++ b/Makefile
++@@ -255,12 +255,6 @@ $(man7): Doc/ttman
++ %.7: %.txt
++      $(call cmd,ttman)
++ 
++-Doc/ttman.o: Doc/ttman.c
++-     $(call cmd,hostcc,)
++-
++-Doc/ttman: Doc/ttman.o
++-     $(call cmd,hostld,)
++-
++ quiet_cmd_ttman = MAN    $@
++       cmd_ttman = Doc/ttman $< $@
++ # }}}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e26e916b8dad50779230fdeb98ad5890cb2d8792
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,229 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Thu, 14 Aug 2025 12:44:10 +0300
++Subject: ip/ffmpeg: more precise seeking
++
++av_seek_frame() and avformat_seek_file() seek to nearest "keyframe". For
++codecs like, for example, ape this means that seeking will be very off
++(5 seconds or more). So what we do is:
++1. seek to nearest "keyframe" before the desired time,
++2. discard some frames to approach the desired time.
++---
++ ip/ffmpeg.c | 154 +++++++++++++++++++++++++++++++++++++-----------------------
++ 1 file changed, 94 insertions(+), 60 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index 21b9a01..ecbf005 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -44,6 +44,8 @@ struct ffmpeg_input {
++      AVPacket pkt;
++      int curr_pkt_size;
++      uint8_t *curr_pkt_buf;
+++     int64_t seek_ts;
+++     int64_t prev_frame_end;
++      int stream_index;
++ 
++      unsigned long curr_size;
++@@ -76,6 +78,8 @@ static struct ffmpeg_input *ffmpeg_input_create(void)
++              return NULL;
++      }
++      input->curr_pkt_size = 0;
+++     input->seek_ts = -1;
+++     input->prev_frame_end = -1;
++      input->curr_pkt_buf = input->pkt.data;
++      return input;
++ }
++@@ -314,10 +318,7 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++ #else
++      AVFrame *frame = avcodec_alloc_frame();
++ #endif
++-     int got_frame;
++      while (1) {
++-             int len;
++-
++              if (input->curr_pkt_size <= 0) {
++ #if LIBAVCODEC_VERSION_MAJOR >= 56
++                      av_packet_unref(&input->pkt);
++@@ -333,78 +334,108 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++ #endif
++                              return 0;
++                      }
++-                     if (input->pkt.stream_index == input->stream_index) {
++-                             input->curr_pkt_size = input->pkt.size;
++-                             input->curr_pkt_buf = input->pkt.data;
++-                             input->curr_size += input->pkt.size;
++-                             input->curr_duration += input->pkt.duration;
++-                     }
++-                     continue;
++-             }
++ 
++-             {
++-                     AVPacket avpkt;
++-                     av_new_packet(&avpkt, input->curr_pkt_size);
++-                     memcpy(avpkt.data, input->curr_pkt_buf, input->curr_pkt_size);
+++                     if (input->pkt.stream_index != input->stream_index)
+++                             continue;
+++                     input->curr_pkt_size = input->pkt.size;
+++                     input->curr_pkt_buf = input->pkt.data;
+++                     input->curr_size += input->pkt.size;
+++                     input->curr_duration += input->pkt.duration;
+++
++ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++-                     int send_result = avcodec_send_packet(cc, &avpkt);
++-                     if (send_result != 0) {
++-                             if (send_result != AVERROR(EAGAIN)) {
++-                                     d_print("avcodec_send_packet() returned %d\n", send_result);
++-                                     char errstr[AV_ERROR_MAX_STRING_SIZE];
++-                                     if (!av_strerror(send_result, errstr, AV_ERROR_MAX_STRING_SIZE ))
++-                                     {
++-                                             d_print("av_strerror(): %s\n", errstr);
++-                                     } else {
++-                                             d_print("av_strerror(): Description for error cannot be found\n");
++-                                     }
++-                                     av_packet_unref(&avpkt);
++-                                     return -IP_ERROR_INTERNAL;
+++                     int send_result = avcodec_send_packet(cc, &input->pkt);
+++                     if (send_result != 0 && send_result != AVERROR(EAGAIN)) {
+++                             d_print("avcodec_send_packet() returned %d\n", send_result);
+++                             char errstr[AV_ERROR_MAX_STRING_SIZE];
+++                             if (!av_strerror(send_result, errstr, AV_ERROR_MAX_STRING_SIZE ))
+++                             {
+++                                     d_print("av_strerror(): %s\n", errstr);
+++                             } else {
+++                                     d_print("av_strerror(): Description for error cannot be found\n");
++                              }
++-                             len = 0;
++-                     } else {
++-                             len = input->curr_pkt_size;
+++                             return -IP_ERROR_INTERNAL;
++                      }
++-
++-                     int recv_result = avcodec_receive_frame(cc, frame);
++-                     got_frame = (recv_result == 0) ? 1 : 0;
++-#else
++-                     len = avcodec_decode_audio4(cc, frame, &got_frame, &avpkt);
++-#endif
++-#if LIBAVCODEC_VERSION_MAJOR >= 56
++-                     av_packet_unref(&avpkt);
++-#else
++-                     av_free_packet(&avpkt);
++ #endif
++              }
+++
+++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+++             int recv_result = avcodec_receive_frame(cc, frame);
+++             if (recv_result < 0) {
+++                     input->curr_pkt_size = 0;
+++                     continue;
+++             }
+++#else
+++             int got_frame;
+++             int len = avcodec_decode_audio4(cc, frame, &got_frame, &input->pkt);
++              if (len < 0) {
++                      /* this is often reached when seeking, not sure why */
++                      input->curr_pkt_size = 0;
++                      continue;
++              }
++-             input->curr_pkt_size -= len;
++-             input->curr_pkt_buf += len;
++-             if (got_frame) {
++-                     int res = swr_convert(swr,
++-                                     &output->buffer,
++-                                     frame->nb_samples,
++-                                     (const uint8_t **)frame->extended_data,
++-                                     frame->nb_samples);
++-                     if (res < 0)
++-                             res = 0;
++-                     output->buffer_pos = output->buffer;
+++             if (!got_frame)
+++                     continue;
+++#endif
+++
+++             int64_t frame_ts = -1;
+++             if (frame->pts)
+++                     frame_ts = frame->pts;
+++             else if (frame->pkt_pts)
+++                     frame_ts = frame->pkt_pts;
+++             else if (frame->pkt_dts)
+++                     frame_ts = frame->pkt_dts;
+++
+++             const uint8_t **in = (const uint8_t **)frame->extended_data;
+++             int in_count = frame->nb_samples;
+++             if (input->seek_ts > 0 && (frame_ts >= 0 || input->prev_frame_end >= 0)) {
+++                     struct ffmpeg_private *priv = ip_data->private;
+++                     AVStream *st = priv->input_context->streams[priv->input->stream_index];
+++                     if (frame_ts >= 0)
+++                             frame_ts = av_rescale_q(frame_ts, st->time_base, AV_TIME_BASE_Q);
+++                     else
+++                             frame_ts = input->prev_frame_end;
+++                     int64_t frame_dur = av_rescale(frame->nb_samples, AV_TIME_BASE, sf_get_rate(ip_data->sf));
+++                     int64_t frame_end = frame_ts + frame_dur;
+++                     input->prev_frame_end = frame_end;
+++                     d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n", input->seek_ts, frame_ts, frame_end);
+++                     if (frame_end <= input->seek_ts)
+++                             continue;
+++
+++                     /* skip part of this frame */
+++                     int64_t skip_samples = av_rescale(input->seek_ts - frame_ts, sf_get_rate(ip_data->sf), AV_TIME_BASE);
+++                     in_count -= skip_samples;
+++                     if (av_sample_fmt_is_planar(frame->format)) {
+++                             for (int i = 0; i < cc->channels; i++) {
+++                                     in[i] += skip_samples * sf_get_sample_size(ip_data->sf);
+++                             }
+++                     } else {
+++                             *in += skip_samples * cc->channels * sf_get_sample_size(ip_data->sf);
+++                     }
+++
+++                     input->seek_ts = -1;
+++                     input->prev_frame_end = -1;
+++             }
+++
+++             int res = swr_convert(swr,
+++                             &output->buffer,
+++                             frame->nb_samples,
+++                             in,
+++                             in_count);
+++             if (res < 0)
+++                     res = 0;
+++
+++             output->buffer_pos = output->buffer;
++ #if LIBAVCODEC_VERSION_MAJOR >= 60
++-                     output->buffer_used_len = res * cc->ch_layout.nb_channels * sf_get_sample_size(ip_data->sf);
+++             output->buffer_used_len = res * cc->ch_layout.nb_channels * sf_get_sample_size(ip_data->sf);
++ #else
++-                     output->buffer_used_len = res * cc->channels * sf_get_sample_size(ip_data->sf);
+++             output->buffer_used_len = res * cc->channels * sf_get_sample_size(ip_data->sf);
++ #endif
+++
++ #if LIBAVCODEC_VERSION_MAJOR >= 56
++-                     av_frame_free(&frame);
+++             av_frame_free(&frame);
++ #else
++-                     avcodec_free_frame(&frame);
+++             avcodec_free_frame(&frame);
++ #endif
++-                     return output->buffer_used_len;
++-             }
+++             return output->buffer_used_len;
++      }
++      /* This should never get here. */
++      return -IP_ERROR_INTERNAL;
++@@ -437,13 +468,16 @@ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
++      AVStream *st = priv->input_context->streams[priv->input->stream_index];
++      int ret;
++ 
++-     int64_t pts = av_rescale_q(offset * AV_TIME_BASE, AV_TIME_BASE_Q, st->time_base);
+++     priv->input->seek_ts = offset * AV_TIME_BASE;
+++     priv->input->prev_frame_end = -1;
+++     int64_t ts = av_rescale(offset, st->time_base.den, st->time_base.num);
++ 
++      avcodec_flush_buffers(priv->codec_context);
++      /* Force reading a new packet in next ffmpeg_fill_buffer(). */
++      priv->input->curr_pkt_size = 0;
++ 
++-     ret = av_seek_frame(priv->input_context, priv->input->stream_index, pts, 0);
+++     ret = avformat_seek_file(priv->input_context,
+++                     priv->input->stream_index, 0, ts, ts, 0);
++ 
++      if (ret < 0) {
++              return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1e0a6342fa0bddb19904559e5d91ae0272267c9b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,53 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Fri, 15 Aug 2025 21:42:19 +0300
++Subject: ip/ffmpeg: skip samples only when needed
++
++---
++ ip/ffmpeg.c | 32 ++++++++++++++++++--------------
++ 1 file changed, 18 insertions(+), 14 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index ecbf005..5f5a4f3 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -393,22 +393,26 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++                              frame_ts = av_rescale_q(frame_ts, st->time_base, AV_TIME_BASE_Q);
++                      else
++                              frame_ts = input->prev_frame_end;
++-                     int64_t frame_dur = av_rescale(frame->nb_samples, AV_TIME_BASE, sf_get_rate(ip_data->sf));
++-                     int64_t frame_end = frame_ts + frame_dur;
++-                     input->prev_frame_end = frame_end;
++-                     d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n", input->seek_ts, frame_ts, frame_end);
++-                     if (frame_end <= input->seek_ts)
++-                             continue;
++ 
++-                     /* skip part of this frame */
++-                     int64_t skip_samples = av_rescale(input->seek_ts - frame_ts, sf_get_rate(ip_data->sf), AV_TIME_BASE);
++-                     in_count -= skip_samples;
++-                     if (av_sample_fmt_is_planar(frame->format)) {
++-                             for (int i = 0; i < cc->channels; i++) {
++-                                     in[i] += skip_samples * sf_get_sample_size(ip_data->sf);
+++                     if (frame_ts < input->seek_ts) {
+++                             int64_t frame_dur = av_rescale(frame->nb_samples, AV_TIME_BASE, sf_get_rate(ip_data->sf));
+++                             int64_t frame_end = frame_ts + frame_dur;
+++                             input->prev_frame_end = frame_end;
+++                             d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n", input->seek_ts, frame_ts, frame_end);
+++                             if (frame_end <= input->seek_ts)
+++                                     continue;
+++
+++                             /* skip part of this frame */
+++                             int64_t skip_samples = av_rescale(input->seek_ts - frame_ts, sf_get_rate(ip_data->sf), AV_TIME_BASE);
+++                             in_count -= skip_samples;
+++                             if (av_sample_fmt_is_planar(frame->format)) {
+++                                     for (int i = 0; i < cc->channels; i++) {
+++                                             in[i] += skip_samples * sf_get_sample_size(ip_data->sf);
+++                                     }
+++                             } else {
+++                                     *in += skip_samples * cc->channels * sf_get_sample_size(ip_data->sf);
++                              }
++-                     } else {
++-                             *in += skip_samples * cc->channels * sf_get_sample_size(ip_data->sf);
+++                             d_print("skipping %ld samples\n", skip_samples);
++                      }
++ 
++                      input->seek_ts = -1;
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..20aebf0469ecacfaa433bc643aa4ce8ea869101b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,342 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sat, 16 Aug 2025 02:43:55 +0300
++Subject: ip/ffmpeg: remove excessive version checks
++
++ffmpeg download page states that v4.0.6 has
++- libavutil 56.14.100
++- libavcodec 58.18.100
++- libavformat 58.12.100
++(https://ffmpeg.org/olddownload.html)
++
++After removing all checks for versions lower than these, the plugin
++still compiles with v3.3.9 headers.
++
++After all, why be better with compatibility than developers themselves?
++---
++ ip/ffmpeg.c | 109 +++++++++++++-----------------------------------------------
++ 1 file changed, 23 insertions(+), 86 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index 5f5a4f3..f6a11f4 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -25,7 +25,6 @@
++ #include "../config/ffmpeg.h"
++ #endif
++ 
++-#include <stdio.h>
++ #include <libavcodec/avcodec.h>
++ #include <libavformat/avformat.h>
++ #include <libavformat/avio.h>
++@@ -43,7 +42,6 @@
++ struct ffmpeg_input {
++      AVPacket pkt;
++      int curr_pkt_size;
++-     uint8_t *curr_pkt_buf;
++      int64_t seek_ts;
++      int64_t prev_frame_end;
++      int stream_index;
++@@ -80,17 +78,12 @@ static struct ffmpeg_input *ffmpeg_input_create(void)
++      input->curr_pkt_size = 0;
++      input->seek_ts = -1;
++      input->prev_frame_end = -1;
++-     input->curr_pkt_buf = input->pkt.data;
++      return input;
++ }
++ 
++ static void ffmpeg_input_free(struct ffmpeg_input *input)
++ {
++-#if LIBAVCODEC_VERSION_MAJOR >= 56
++      av_packet_unref(&input->pkt);
++-#else
++-     av_free_packet(&input->pkt);
++-#endif
++      free(input);
++ }
++ 
++@@ -132,7 +125,7 @@ static void ffmpeg_init(void)
++ 
++      av_log_set_level(AV_LOG_QUIET);
++ 
++-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100)
+++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
++      /* We could register decoders explicitly to save memory, but we have to
++       * be careful about compatibility. */
++      av_register_all();
++@@ -149,9 +142,7 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++      AVCodec const *codec;
++      AVCodecContext *cc = NULL;
++      AVFormatContext *ic = NULL;
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++      AVCodecParameters *cp = NULL;
++-#endif
++      SwrContext *swr = NULL;
++ 
++      ffmpeg_init();
++@@ -171,20 +162,11 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++              }
++ 
++              for (i = 0; i < ic->nb_streams; i++) {
++-
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++                      cp = ic->streams[i]->codecpar;
++                      if (cp->codec_type == AVMEDIA_TYPE_AUDIO) {
++                              stream_index = i;
++                              break;
++                      }
++-#else
++-                     cc = ic->streams[i]->codec;
++-                     if (cc->codec_type == AVMEDIA_TYPE_AUDIO) {
++-                             stream_index = i;
++-                             break;
++-                     }
++-#endif
++              }
++ 
++              if (stream_index == -1) {
++@@ -193,13 +175,9 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++                      break;
++              }
++ 
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++              codec = avcodec_find_decoder(cp->codec_id);
++              cc = avcodec_alloc_context3(codec);
++              avcodec_parameters_to_context(cc, cp);
++-#else
++-             codec = avcodec_find_decoder(cc->codec_id);
++-#endif
++              if (!codec) {
++                      d_print("codec not found: %d, %s\n", cc->codec_id, avcodec_get_name(cc->codec_id));
++                      err = -IP_ERROR_UNSUPPORTED_FILE_TYPE;
++@@ -217,9 +195,7 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++ 
++      if (err < 0) {
++              /* Clean up.  cc is never opened at this point.  (See above assumption.) */
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++              avcodec_free_context(&cc);
++-#endif
++              avformat_close_input(&ic);
++              return err;
++      }
++@@ -231,9 +207,7 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++      priv->input = ffmpeg_input_create();
++      if (priv->input == NULL) {
++              avcodec_close(cc);
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++              avcodec_free_context(&cc);
++-#endif
++              avformat_close_input(&ic);
++              free(priv);
++              return -IP_ERROR_INTERNAL;
++@@ -244,7 +218,7 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++      /* Prepare for resampling. */
++      out_sample_rate = min_u(cc->sample_rate, 384000);
++      swr = swr_alloc();
++-#if LIBAVCODEC_VERSION_MAJOR >= 60
+++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
++      if (cc->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
++              av_channel_layout_default(&cc->ch_layout, cc->ch_layout.nb_channels);
++      av_opt_set_chlayout(swr, "in_chlayout",   &cc->ch_layout, 0);
++@@ -259,7 +233,7 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++      priv->swr = swr;
++ 
++      ip_data->private = priv;
++-#if LIBAVCODEC_VERSION_MAJOR >= 60
+++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
++      ip_data->sf = sf_rate(out_sample_rate) | sf_channels(cc->ch_layout.nb_channels);
++ #else
++      ip_data->sf = sf_rate(out_sample_rate) | sf_channels(cc->channels);
++@@ -281,10 +255,12 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++      }
++      swr_init(swr);
++      ip_data->sf |= sf_host_endian();
++-#if LIBAVCODEC_VERSION_MAJOR >= 60
++-     channel_map_init_waveex(cc->ch_layout.nb_channels, cc->ch_layout.u.mask, ip_data->channel_map);
+++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
+++     channel_map_init_waveex(cc->ch_layout.nb_channels,
+++                     cc->ch_layout.u.mask, ip_data->channel_map);
++ #else
++-     channel_map_init_waveex(cc->channels, cc->channel_layout, ip_data->channel_map);
+++     channel_map_init_waveex(cc->channels,
+++                     cc->channel_layout, ip_data->channel_map);
++ #endif
++      return 0;
++ }
++@@ -294,9 +270,7 @@ static int ffmpeg_close(struct input_plugin_data *ip_data)
++      struct ffmpeg_private *priv = ip_data->private;
++ 
++      avcodec_close(priv->codec_context);
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++      avcodec_free_context(&priv->codec_context);
++-#endif
++      avformat_close_input(&priv->input_context);
++      swr_free(&priv->swr);
++      ffmpeg_input_free(priv->input);
++@@ -310,39 +284,27 @@ static int ffmpeg_close(struct input_plugin_data *ip_data)
++  * This returns the number of bytes added to the buffer.
++  * It returns < 0 on error.  0 on EOF.
++  */
++-static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext *ic, AVCodecContext *cc,
++-                           struct ffmpeg_input *input, struct ffmpeg_output *output, SwrContext *swr)
+++static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data,
+++             AVFormatContext *ic, AVCodecContext *cc,
+++             struct ffmpeg_input *input, struct ffmpeg_output *output,
+++             SwrContext *swr)
++ {
++-#if LIBAVCODEC_VERSION_MAJOR >= 56
++      AVFrame *frame = av_frame_alloc();
++-#else
++-     AVFrame *frame = avcodec_alloc_frame();
++-#endif
++      while (1) {
++              if (input->curr_pkt_size <= 0) {
++-#if LIBAVCODEC_VERSION_MAJOR >= 56
++                      av_packet_unref(&input->pkt);
++-#else
++-                     av_free_packet(&input->pkt);
++-#endif
++                      if (av_read_frame(ic, &input->pkt) < 0) {
++                              /* Force EOF once we can read no longer. */
++-#if LIBAVCODEC_VERSION_MAJOR >= 56
++                              av_frame_free(&frame);
++-#else
++-                             avcodec_free_frame(&frame);
++-#endif
++                              return 0;
++                      }
++ 
++                      if (input->pkt.stream_index != input->stream_index)
++                              continue;
++                      input->curr_pkt_size = input->pkt.size;
++-                     input->curr_pkt_buf = input->pkt.data;
++                      input->curr_size += input->pkt.size;
++                      input->curr_duration += input->pkt.duration;
++ 
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++                      int send_result = avcodec_send_packet(cc, &input->pkt);
++                      if (send_result != 0 && send_result != AVERROR(EAGAIN)) {
++                              d_print("avcodec_send_packet() returned %d\n", send_result);
++@@ -355,32 +317,17 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++                              }
++                              return -IP_ERROR_INTERNAL;
++                      }
++-#endif
++              }
++ 
++-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++              int recv_result = avcodec_receive_frame(cc, frame);
++              if (recv_result < 0) {
++                      input->curr_pkt_size = 0;
++                      continue;
++              }
++-#else
++-             int got_frame;
++-             int len = avcodec_decode_audio4(cc, frame, &got_frame, &input->pkt);
++-             if (len < 0) {
++-                     /* this is often reached when seeking, not sure why */
++-                     input->curr_pkt_size = 0;
++-                     continue;
++-             }
++-             if (!got_frame)
++-                     continue;
++-#endif
++ 
++              int64_t frame_ts = -1;
++              if (frame->pts)
++                      frame_ts = frame->pts;
++-             else if (frame->pkt_pts)
++-                     frame_ts = frame->pkt_pts;
++              else if (frame->pkt_dts)
++                      frame_ts = frame->pkt_dts;
++ 
++@@ -395,7 +342,7 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++                              frame_ts = input->prev_frame_end;
++ 
++                      if (frame_ts < input->seek_ts) {
++-                             int64_t frame_dur = av_rescale(frame->nb_samples, AV_TIME_BASE, sf_get_rate(ip_data->sf));
+++                             int64_t frame_dur = av_rescale(frame->nb_samples, AV_TIME_BASE, frame->sample_rate);
++                              int64_t frame_end = frame_ts + frame_dur;
++                              input->prev_frame_end = frame_end;
++                              d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n", input->seek_ts, frame_ts, frame_end);
++@@ -403,14 +350,14 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++                                      continue;
++ 
++                              /* skip part of this frame */
++-                             int64_t skip_samples = av_rescale(input->seek_ts - frame_ts, sf_get_rate(ip_data->sf), AV_TIME_BASE);
+++                             int64_t skip_samples = av_rescale(input->seek_ts - frame_ts, frame->sample_rate, AV_TIME_BASE);
++                              in_count -= skip_samples;
++                              if (av_sample_fmt_is_planar(frame->format)) {
++-                                     for (int i = 0; i < cc->channels; i++) {
+++                                     for (int i = 0; i < sf_get_channels(ip_data->sf); i++) {
++                                              in[i] += skip_samples * sf_get_sample_size(ip_data->sf);
++                                      }
++                              } else {
++-                                     *in += skip_samples * cc->channels * sf_get_sample_size(ip_data->sf);
+++                                     *in += skip_samples * sf_get_frame_size(ip_data->sf);
++                              }
++                              d_print("skipping %ld samples\n", skip_samples);
++                      }
++@@ -428,17 +375,9 @@ static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data, AVFormatContext
++                      res = 0;
++ 
++              output->buffer_pos = output->buffer;
++-#if LIBAVCODEC_VERSION_MAJOR >= 60
++-             output->buffer_used_len = res * cc->ch_layout.nb_channels * sf_get_sample_size(ip_data->sf);
++-#else
++-             output->buffer_used_len = res * cc->channels * sf_get_sample_size(ip_data->sf);
++-#endif
+++             output->buffer_used_len = res * sf_get_frame_size(ip_data->sf);
++ 
++-#if LIBAVCODEC_VERSION_MAJOR >= 56
++              av_frame_free(&frame);
++-#else
++-             avcodec_free_frame(&frame);
++-#endif
++              return output->buffer_used_len;
++      }
++      /* This should never get here. */
++@@ -453,11 +392,11 @@ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int coun
++      int out_size;
++ 
++      if (output->buffer_used_len == 0) {
++-             rc = ffmpeg_fill_buffer(ip_data, priv->input_context, priv->codec_context,
+++             rc = ffmpeg_fill_buffer(ip_data,
+++                             priv->input_context, priv->codec_context,
++                              priv->input, priv->output, priv->swr);
++-             if (rc <= 0) {
+++             if (rc <= 0)
++                      return rc;
++-             }
++      }
++      out_size = min_i(output->buffer_used_len, count);
++      memcpy(buffer, output->buffer_pos, out_size);
++@@ -477,6 +416,7 @@ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
++      int64_t ts = av_rescale(offset, st->time_base.den, st->time_base.num);
++ 
++      avcodec_flush_buffers(priv->codec_context);
+++     /* TODO: also flush swresample buffers */
++      /* Force reading a new packet in next ffmpeg_fill_buffer(). */
++      priv->input->curr_pkt_size = 0;
++ 
++@@ -501,7 +441,8 @@ static void ffmpeg_read_metadata(struct growing_keyvals *c, AVDictionary *metada
++      }
++ }
++ 
++-static int ffmpeg_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
+++static int ffmpeg_read_comments(struct input_plugin_data *ip_data,
+++             struct keyval **comments)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++      AVFormatContext *ic = priv->input_context;
++@@ -538,11 +479,7 @@ static long ffmpeg_current_bitrate(struct input_plugin_data *ip_data)
++      AVStream *st = priv->input_context->streams[priv->input->stream_index];
++      long bitrate = -1;
++      /* ape codec returns silly numbers */
++-#if LIBAVCODEC_VERSION_MAJOR >= 55
++      if (priv->codec->id == AV_CODEC_ID_APE)
++-#else
++-     if (priv->codec->id == CODEC_ID_APE)
++-#endif
++              return -1;
++      if (priv->input->curr_duration > 0) {
++              double seconds = priv->input->curr_duration * av_q2d(st->time_base);
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..507c6546f943b7b83d2357a3a84708a918c65450
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,777 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 04:05:36 +0300
++Subject: ip/ffmpeg: major refactor
++
++---
++ ip/ffmpeg.c | 643 +++++++++++++++++++++++++++++++-----------------------------
++ 1 file changed, 330 insertions(+), 313 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index f6a11f4..42f630e 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -35,84 +35,32 @@
++ #include <libavutil/mathematics.h>
++ #endif
++ 
++-#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
++-#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
++-#endif
+++struct ffmpeg_private {
+++     AVCodecContext *codec_ctx;
+++     AVFormatContext *format_ctx;
+++     AVCodec const *codec;
+++     SwrContext *swr;
+++     int stream_index;
++ 
++-struct ffmpeg_input {
++-     AVPacket pkt;
++-     int curr_pkt_size;
+++     AVPacket *pkt;
+++     AVFrame *frame;
++      int64_t seek_ts;
++      int64_t prev_frame_end;
++-     int stream_index;
++ 
+++     /* A buffer to hold swr_convert()-ed samples */
+++     AVFrame *swr_frame;
+++     int swr_frame_start;
+++
+++     /* Bitrate estimation */
++      unsigned long curr_size;
++      unsigned long curr_duration;
++ };
++ 
++-struct ffmpeg_output {
++-     uint8_t *buffer;
++-     uint8_t *buffer_malloc;
++-     uint8_t *buffer_pos;    /* current buffer position */
++-     int buffer_used_len;
++-};
++-
++-struct ffmpeg_private {
++-     AVCodecContext *codec_context;
++-     AVFormatContext *input_context;
++-     AVCodec const *codec;
++-     SwrContext *swr;
++-
++-     struct ffmpeg_input *input;
++-     struct ffmpeg_output *output;
++-};
++-
++-static struct ffmpeg_input *ffmpeg_input_create(void)
++-{
++-     struct ffmpeg_input *input = xnew(struct ffmpeg_input, 1);
++-
++-     if (av_new_packet(&input->pkt, 0) != 0) {
++-             free(input);
++-             return NULL;
++-     }
++-     input->curr_pkt_size = 0;
++-     input->seek_ts = -1;
++-     input->prev_frame_end = -1;
++-     return input;
++-}
++-
++-static void ffmpeg_input_free(struct ffmpeg_input *input)
++-{
++-     av_packet_unref(&input->pkt);
++-     free(input);
++-}
++-
++-static struct ffmpeg_output *ffmpeg_output_create(void)
++-{
++-     struct ffmpeg_output *output = xnew(struct ffmpeg_output, 1);
++-
++-     output->buffer_malloc = xnew(uint8_t, AVCODEC_MAX_AUDIO_FRAME_SIZE + 15);
++-     output->buffer = output->buffer_malloc;
++-     /* align to 16 bytes so avcodec can SSE/Altivec/etc */
++-     while ((intptr_t) output->buffer % 16)
++-             output->buffer += 1;
++-     output->buffer_pos = output->buffer;
++-     output->buffer_used_len = 0;
++-     return output;
++-}
++-
++-static void ffmpeg_output_free(struct ffmpeg_output *output)
++-{
++-     free(output->buffer_malloc);
++-     output->buffer_malloc = NULL;
++-     output->buffer = NULL;
++-     free(output);
++-}
++-
++-static inline void ffmpeg_buffer_flush(struct ffmpeg_output *output)
+++static const char *ffmpeg_errmsg(int err)
++ {
++-     output->buffer_pos = output->buffer;
++-     output->buffer_used_len = 0;
+++     static char errstr[AV_ERROR_MAX_STRING_SIZE];
+++     av_strerror(err, errstr, AV_ERROR_MAX_STRING_SIZE);
+++     return errstr;
++ }
++ 
++ static void ffmpeg_init(void)
++@@ -132,303 +80,372 @@ static void ffmpeg_init(void)
++ #endif
++ }
++ 
++-static int ffmpeg_open(struct input_plugin_data *ip_data)
+++static int ffmpeg_open_input(struct input_plugin_data *ip_data,
+++             struct ffmpeg_private *priv)
++ {
++-     struct ffmpeg_private *priv;
++-     int err = 0;
++-     int i;
++-     int stream_index = -1;
++-     int out_sample_rate;
++-     AVCodec const *codec;
++-     AVCodecContext *cc = NULL;
++      AVFormatContext *ic = NULL;
+++     AVCodecContext *cc = NULL;
++      AVCodecParameters *cp = NULL;
++-     SwrContext *swr = NULL;
++-
++-     ffmpeg_init();
+++     AVCodec const *codec = NULL;
+++     int stream_index = -1;
++ 
++-     err = avformat_open_input(&ic, ip_data->filename, NULL, NULL);
++-     if (err < 0) {
++-             d_print("av_open failed: %d\n", err);
++-             return -IP_ERROR_FILE_FORMAT;
+++     int err;
+++     int res = avformat_open_input(&ic, ip_data->filename, NULL, NULL);
+++     if (res < 0) {
+++             err = -IP_ERROR_FILE_FORMAT;
+++             goto err;
++      }
++ 
++-     do {
++-             err = avformat_find_stream_info(ic, NULL);
++-             if (err < 0) {
++-                     d_print("unable to find stream info: %d\n", err);
++-                     err = -IP_ERROR_FILE_FORMAT;
++-                     break;
++-             }
++-
++-             for (i = 0; i < ic->nb_streams; i++) {
++-                     cp = ic->streams[i]->codecpar;
++-                     if (cp->codec_type == AVMEDIA_TYPE_AUDIO) {
++-                             stream_index = i;
++-                             break;
++-                     }
++-             }
++-
++-             if (stream_index == -1) {
++-                     d_print("could not find audio stream\n");
++-                     err = -IP_ERROR_FILE_FORMAT;
++-                     break;
++-             }
++-
++-             codec = avcodec_find_decoder(cp->codec_id);
++-             cc = avcodec_alloc_context3(codec);
++-             avcodec_parameters_to_context(cc, cp);
++-             if (!codec) {
++-                     d_print("codec not found: %d, %s\n", cc->codec_id, avcodec_get_name(cc->codec_id));
++-                     err = -IP_ERROR_UNSUPPORTED_FILE_TYPE;
++-                     break;
++-             }
+++     res = avformat_find_stream_info(ic, NULL);
+++     if (res < 0) {
+++             d_print("unable to find stream info\n");
+++             err = -IP_ERROR_FILE_FORMAT;
+++             goto err;
+++     }
++ 
++-             if (avcodec_open2(cc, codec, NULL) < 0) {
++-                     d_print("could not open codec: %d, %s\n", cc->codec_id, avcodec_get_name(cc->codec_id));
++-                     err = -IP_ERROR_UNSUPPORTED_FILE_TYPE;
+++     for (int i = 0; i < ic->nb_streams; i++) {
+++             cp = ic->streams[i]->codecpar;
+++             if (cp->codec_type == AVMEDIA_TYPE_AUDIO) {
+++                     stream_index = i;
++                      break;
++              }
+++     }
++ 
++-             /* We assume below that no more errors follow. */
++-     } while (0);
+++     if (stream_index == -1) {
+++             d_print("could not find audio stream\n");
+++             err = -IP_ERROR_FILE_FORMAT;
+++             goto err_silent;
+++     }
++ 
++-     if (err < 0) {
++-             /* Clean up.  cc is never opened at this point.  (See above assumption.) */
++-             avcodec_free_context(&cc);
++-             avformat_close_input(&ic);
++-             return err;
+++     codec = avcodec_find_decoder(cp->codec_id);
+++     if (!codec) {
+++             d_print("codec (id: %d, name: %s) not found\n",
+++                             cc->codec_id, avcodec_get_name(cc->codec_id));
+++             err = -IP_ERROR_UNSUPPORTED_FILE_TYPE;
+++             goto err_silent;
+++     }
+++     cc = avcodec_alloc_context3(codec);
+++     avcodec_parameters_to_context(cc, cp);
+++
+++     res = avcodec_open2(cc, codec, NULL);
+++     if (res < 0) {
+++             d_print("could not open codec (id: %d, name: %s)\n",
+++                             cc->codec_id, avcodec_get_name(cc->codec_id));
+++             err = -IP_ERROR_UNSUPPORTED_FILE_TYPE;
+++             goto err;
++      }
++ 
++-     priv = xnew(struct ffmpeg_private, 1);
++-     priv->codec_context = cc;
++-     priv->input_context = ic;
+++     priv->format_ctx = ic;
+++     priv->codec_ctx = cc;
++      priv->codec = codec;
++-     priv->input = ffmpeg_input_create();
++-     if (priv->input == NULL) {
++-             avcodec_close(cc);
++-             avcodec_free_context(&cc);
++-             avformat_close_input(&ic);
++-             free(priv);
++-             return -IP_ERROR_INTERNAL;
+++     priv->stream_index = stream_index;
+++     return 0;
+++err:
+++     d_print("%s\n", ffmpeg_errmsg(res));
+++err_silent:
+++     avcodec_free_context(&cc);
+++     avformat_close_input(&ic);
+++     return err;
+++}
+++
+++static void ffmpeg_set_sf_and_swr_opts(SwrContext *swr, AVCodecContext *cc,
+++             sample_format_t *sf_out, enum AVSampleFormat *out_sample_fmt)
+++{
+++     int out_sample_rate = min_u(cc->sample_rate, 384000);
+++     sample_format_t sf = sf_rate(out_sample_rate) | sf_host_endian();
+++     av_opt_set_int(swr, "in_sample_rate", cc->sample_rate, 0);
+++     av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0);
+++
+++     *out_sample_fmt = cc->sample_fmt;
+++     switch (*out_sample_fmt) {
+++             case AV_SAMPLE_FMT_U8:
+++                     sf |= sf_bits(8) | sf_signed(0);
+++                     break;
+++             case AV_SAMPLE_FMT_S32:
+++                     sf |= sf_bits(32) | sf_signed(1);
+++                     break;
+++             default:
+++                     sf |= sf_bits(16) | sf_signed(1);
+++                     *out_sample_fmt = AV_SAMPLE_FMT_S16;
++      }
++-     priv->input->stream_index = stream_index;
++-     priv->output = ffmpeg_output_create();
+++     av_opt_set_sample_fmt(swr, "in_sample_fmt", cc->sample_fmt, 0);
+++     av_opt_set_sample_fmt(swr, "out_sample_fmt", *out_sample_fmt, 0);
++ 
++-     /* Prepare for resampling. */
++-     out_sample_rate = min_u(cc->sample_rate, 384000);
++-     swr = swr_alloc();
++ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
+++     sf |= sf_channels(cc->ch_layout.nb_channels);
+++
++      if (cc->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
++              av_channel_layout_default(&cc->ch_layout, cc->ch_layout.nb_channels);
++-     av_opt_set_chlayout(swr, "in_chlayout",   &cc->ch_layout, 0);
++-     av_opt_set_chlayout(swr, "out_chlayout",  &cc->ch_layout, 0);
+++     av_opt_set_chlayout(swr, "in_chlayout", &cc->ch_layout, 0);
+++     av_opt_set_chlayout(swr, "out_chlayout", &cc->ch_layout, 0);
++ #else
++-     av_opt_set_int(swr, "in_channel_layout",  av_get_default_channel_layout(cc->channels), 0);
++-     av_opt_set_int(swr, "out_channel_layout", av_get_default_channel_layout(cc->channels), 0);
+++     sf |= sf_channels(cc->channels);
+++
+++     av_opt_set_int(swr, "in_channel_layout",
+++                     av_get_default_channel_layout(cc->channels), 0);
+++     av_opt_set_int(swr, "out_channel_layout",
+++                     av_get_default_channel_layout(cc->channels), 0);
++ #endif
++-     av_opt_set_int(swr, "in_sample_rate",     cc->sample_rate, 0);
++-     av_opt_set_int(swr, "out_sample_rate",    out_sample_rate, 0);
++-     av_opt_set_sample_fmt(swr, "in_sample_fmt",  cc->sample_fmt, 0);
++-     priv->swr = swr;
++ 
++-     ip_data->private = priv;
+++     *sf_out = sf;
+++}
+++
+++static int ffmpeg_init_swr_frame(struct ffmpeg_private *priv,
+++             sample_format_t sf, enum AVSampleFormat out_sample_fmt)
+++{
+++     AVCodecContext *cc = priv->codec_ctx;
+++     AVFrame *frame = av_frame_alloc();
+++
++ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
++-     ip_data->sf = sf_rate(out_sample_rate) | sf_channels(cc->ch_layout.nb_channels);
+++     av_channel_layout_copy(&frame->ch_layout, &cc->ch_layout);
++ #else
++-     ip_data->sf = sf_rate(out_sample_rate) | sf_channels(cc->channels);
+++     frame->channel_layout = av_get_default_channel_layout(cc->channels);
++ #endif
++-     switch (cc->sample_fmt) {
++-     case AV_SAMPLE_FMT_U8:
++-             ip_data->sf |= sf_bits(8) | sf_signed(0);
++-             av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_U8,  0);
++-             break;
++-     case AV_SAMPLE_FMT_S32:
++-             ip_data->sf |= sf_bits(32) | sf_signed(1);
++-             av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S32,  0);
++-             break;
++-     /* AV_SAMPLE_FMT_S16 */
++-     default:
++-             ip_data->sf |= sf_bits(16) | sf_signed(1);
++-             av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16,  0);
++-             break;
+++
+++     frame->sample_rate = sf_get_rate(sf);
+++     frame->format = out_sample_fmt;
+++
+++     /* NOTE: 10 sec is probably too much, but the amount of space
+++      * needed for swr_convert() is unpredictable */
+++     frame->nb_samples = 10 * sf_get_rate(sf);
+++     int res = av_frame_get_buffer(frame, 0);
+++     if (res < 0) {
+++             d_print("av_frame_get_buffer(): %s\n", ffmpeg_errmsg(res));
+++             return -IP_ERROR_INTERNAL;
++      }
++-     swr_init(swr);
++-     ip_data->sf |= sf_host_endian();
+++     frame->nb_samples = 0;
+++
+++     priv->swr_frame = frame;
+++     return 0;
+++}
+++
+++static void ffmpeg_free(struct ffmpeg_private *priv)
+++{
+++     avcodec_close(priv->codec_ctx);
+++     avcodec_free_context(&priv->codec_ctx);
+++     avformat_close_input(&priv->format_ctx);
+++
+++     swr_free(&priv->swr);
+++
+++     av_frame_free(&priv->frame);
+++     av_packet_free(&priv->pkt);
+++     av_frame_free(&priv->swr_frame);
+++}
+++
+++static int ffmpeg_open(struct input_plugin_data *ip_data)
+++{
+++     struct ffmpeg_private priv;
+++     enum AVSampleFormat out_sample_fmt;
+++     memset(&priv, 0, sizeof(struct ffmpeg_private));
+++
+++     ffmpeg_init();
+++
+++     int err = ffmpeg_open_input(ip_data, &priv);
+++     if (err < 0)
+++             return err;
+++
+++     priv.pkt = av_packet_alloc();
+++     priv.frame = av_frame_alloc();
+++     priv.seek_ts = -1;
+++     priv.prev_frame_end = -1;
+++
+++     priv.swr = swr_alloc();
+++     ffmpeg_set_sf_and_swr_opts(priv.swr, priv.codec_ctx,
+++                     &ip_data->sf, &out_sample_fmt);
+++     swr_init(priv.swr);
+++
+++     err = ffmpeg_init_swr_frame(&priv, ip_data->sf, out_sample_fmt);
+++     if (err < 0) {
+++             ffmpeg_free(&priv);
+++             return err;
+++     }
+++
++ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
++-     channel_map_init_waveex(cc->ch_layout.nb_channels,
++-                     cc->ch_layout.u.mask, ip_data->channel_map);
+++     channel_map_init_waveex(priv.codec_ctx->ch_layout.nb_channels,
+++                     priv.codec_ctx->ch_layout.u.mask, ip_data->channel_map);
++ #else
++-     channel_map_init_waveex(cc->channels,
++-                     cc->channel_layout, ip_data->channel_map);
+++     channel_map_init_waveex(priv.codec_ctx->channels,
+++                     priv.codec_ctx->channel_layout, ip_data->channel_map);
++ #endif
+++
+++     ip_data->private = xnew(struct ffmpeg_private, 1);
+++     memcpy(ip_data->private, &priv, sizeof(struct ffmpeg_private));
++      return 0;
++ }
++ 
++ static int ffmpeg_close(struct input_plugin_data *ip_data)
++ {
++-     struct ffmpeg_private *priv = ip_data->private;
++-
++-     avcodec_close(priv->codec_context);
++-     avcodec_free_context(&priv->codec_context);
++-     avformat_close_input(&priv->input_context);
++-     swr_free(&priv->swr);
++-     ffmpeg_input_free(priv->input);
++-     ffmpeg_output_free(priv->output);
++-     free(priv);
+++     ffmpeg_free(ip_data->private);
+++     free(ip_data->private);
++      ip_data->private = NULL;
++      return 0;
++ }
++ 
++ /*
++- * This returns the number of bytes added to the buffer.
++- * It returns < 0 on error.  0 on EOF.
+++ * return:
+++ *    0 - retry
+++ *   >0 - ok
++  */
++-static int ffmpeg_fill_buffer(struct input_plugin_data *ip_data,
++-             AVFormatContext *ic, AVCodecContext *cc,
++-             struct ffmpeg_input *input, struct ffmpeg_output *output,
++-             SwrContext *swr)
+++static int ffmpeg_seek_into_frame(struct ffmpeg_private *priv, int64_t frame_ts)
++ {
++-     AVFrame *frame = av_frame_alloc();
++-     while (1) {
++-             if (input->curr_pkt_size <= 0) {
++-                     av_packet_unref(&input->pkt);
++-                     if (av_read_frame(ic, &input->pkt) < 0) {
++-                             /* Force EOF once we can read no longer. */
++-                             av_frame_free(&frame);
++-                             return 0;
++-                     }
++-
++-                     if (input->pkt.stream_index != input->stream_index)
++-                             continue;
++-                     input->curr_pkt_size = input->pkt.size;
++-                     input->curr_size += input->pkt.size;
++-                     input->curr_duration += input->pkt.duration;
++-
++-                     int send_result = avcodec_send_packet(cc, &input->pkt);
++-                     if (send_result != 0 && send_result != AVERROR(EAGAIN)) {
++-                             d_print("avcodec_send_packet() returned %d\n", send_result);
++-                             char errstr[AV_ERROR_MAX_STRING_SIZE];
++-                             if (!av_strerror(send_result, errstr, AV_ERROR_MAX_STRING_SIZE ))
++-                             {
++-                                     d_print("av_strerror(): %s\n", errstr);
++-                             } else {
++-                                     d_print("av_strerror(): Description for error cannot be found\n");
++-                             }
++-                             return -IP_ERROR_INTERNAL;
++-                     }
++-             }
+++     if (frame_ts >= 0) {
+++             AVStream *s = priv->format_ctx->streams[priv->stream_index];
+++             frame_ts = av_rescale_q(frame_ts, s->time_base, AV_TIME_BASE_Q);
+++     } else {
+++             frame_ts = priv->prev_frame_end;
+++     }
++ 
++-             int recv_result = avcodec_receive_frame(cc, frame);
++-             if (recv_result < 0) {
++-                     input->curr_pkt_size = 0;
++-                     continue;
++-             }
+++     if (frame_ts >= priv->seek_ts)
+++             return 1;
++ 
++-             int64_t frame_ts = -1;
++-             if (frame->pts)
++-                     frame_ts = frame->pts;
++-             else if (frame->pkt_dts)
++-                     frame_ts = frame->pkt_dts;
++-
++-             const uint8_t **in = (const uint8_t **)frame->extended_data;
++-             int in_count = frame->nb_samples;
++-             if (input->seek_ts > 0 && (frame_ts >= 0 || input->prev_frame_end >= 0)) {
++-                     struct ffmpeg_private *priv = ip_data->private;
++-                     AVStream *st = priv->input_context->streams[priv->input->stream_index];
++-                     if (frame_ts >= 0)
++-                             frame_ts = av_rescale_q(frame_ts, st->time_base, AV_TIME_BASE_Q);
++-                     else
++-                             frame_ts = input->prev_frame_end;
++-
++-                     if (frame_ts < input->seek_ts) {
++-                             int64_t frame_dur = av_rescale(frame->nb_samples, AV_TIME_BASE, frame->sample_rate);
++-                             int64_t frame_end = frame_ts + frame_dur;
++-                             input->prev_frame_end = frame_end;
++-                             d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n", input->seek_ts, frame_ts, frame_end);
++-                             if (frame_end <= input->seek_ts)
++-                                     continue;
++-
++-                             /* skip part of this frame */
++-                             int64_t skip_samples = av_rescale(input->seek_ts - frame_ts, frame->sample_rate, AV_TIME_BASE);
++-                             in_count -= skip_samples;
++-                             if (av_sample_fmt_is_planar(frame->format)) {
++-                                     for (int i = 0; i < sf_get_channels(ip_data->sf); i++) {
++-                                             in[i] += skip_samples * sf_get_sample_size(ip_data->sf);
++-                                     }
++-                             } else {
++-                                     *in += skip_samples * sf_get_frame_size(ip_data->sf);
++-                             }
++-                             d_print("skipping %ld samples\n", skip_samples);
++-                     }
++-
++-                     input->seek_ts = -1;
++-                     input->prev_frame_end = -1;
++-             }
+++     int64_t frame_dur = av_rescale(priv->frame->nb_samples,
+++                     AV_TIME_BASE, priv->frame->sample_rate);
+++     int64_t frame_end = frame_ts + frame_dur;
+++     priv->prev_frame_end = frame_end;
+++
+++     d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n",
+++                     priv->seek_ts, frame_ts, frame_end);
+++
+++     if (frame_end <= priv->seek_ts)
+++             return 0;
+++
+++     int64_t skip_samples = av_rescale(priv->seek_ts - frame_ts,
+++                     priv->frame->sample_rate, AV_TIME_BASE);
+++     priv->frame->nb_samples -= skip_samples;
+++
+++     int bps = av_get_bytes_per_sample(priv->frame->format);
+++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
+++     int channels = priv->codec_ctx->ch_layout.nb_channels;
+++#else
+++     int channels = priv->codec_ctx->channels;
+++#endif
+++
+++     /* Just modify frame's data pointer because it's throw-away */
+++     if (av_sample_fmt_is_planar(priv->frame->format)) {
+++             for (int i = 0; i < channels; i++)
+++                     priv->frame->extended_data[i] += skip_samples * bps;
+++     } else {
+++             priv->frame->extended_data[0] += skip_samples * channels * bps;
+++     }
+++     d_print("skipping %ld samples\n", skip_samples);
+++     return 1;
+++}
++ 
++-             int res = swr_convert(swr,
++-                             &output->buffer,
++-                             frame->nb_samples,
++-                             in,
++-                             in_count);
+++/*
+++ * return:
+++ *   <0 - error
+++ *    0 - retry
+++ *   >0 - ok
+++ */
+++static int ffmpeg_get_frame(struct ffmpeg_private *priv)
+++{
+++     int res = avcodec_receive_frame(priv->codec_ctx, priv->frame);
+++     if (res == AVERROR(EAGAIN)) {
+++             av_packet_unref(priv->pkt);
+++             res = av_read_frame(priv->format_ctx, priv->pkt);
++              if (res < 0)
++-                     res = 0;
+++                     return res;
+++
+++             if (priv->pkt->stream_index != priv->stream_index)
+++                     return 0;
++ 
++-             output->buffer_pos = output->buffer;
++-             output->buffer_used_len = res * sf_get_frame_size(ip_data->sf);
+++             priv->curr_size += priv->pkt->size;
+++             priv->curr_duration += priv->pkt->duration;
++ 
++-             av_frame_free(&frame);
++-             return output->buffer_used_len;
+++             res = avcodec_send_packet(priv->codec_ctx, priv->pkt);
+++             if (res == AVERROR(EAGAIN))
+++                     return 0;
++      }
++-     /* This should never get here. */
++-     return -IP_ERROR_INTERNAL;
+++     if (res < 0)
+++             return res;
+++
+++     int64_t frame_ts = -1;
+++     if (priv->frame->pts >= 0)
+++             frame_ts = priv->frame->pts;
+++     else if (priv->frame->pkt_dts >= 0)
+++             frame_ts = priv->frame->pkt_dts;
+++
+++     if (priv->seek_ts > 0 && (frame_ts >= 0 || priv->prev_frame_end >= 0)) {
+++             if (ffmpeg_seek_into_frame(priv, frame_ts) == 0)
+++                     return 0;
+++             priv->seek_ts = -1;
+++             priv->prev_frame_end = -1;
+++     }
+++     return 1;
+++}
+++
+++static int ffmpeg_convert_frame(struct ffmpeg_private *priv)
+++{
+++     int res = swr_convert(priv->swr,
+++                     priv->swr_frame->extended_data,
+++                     /* TODO: proper buffer capacity */
+++                     priv->frame->nb_samples,
+++                     (const uint8_t **)priv->frame->extended_data,
+++                     priv->frame->nb_samples);
+++     if (res >= 0) {
+++             priv->swr_frame->nb_samples = res;
+++             priv->swr_frame_start = 0;
+++     }
+++     return res;
++ }
++ 
++ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int count)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++-     struct ffmpeg_output *output = priv->output;
++-     int rc;
++-     int out_size;
++-
++-     if (output->buffer_used_len == 0) {
++-             rc = ffmpeg_fill_buffer(ip_data,
++-                             priv->input_context, priv->codec_context,
++-                             priv->input, priv->output, priv->swr);
++-             if (rc <= 0)
++-                     return rc;
+++     int written = 0;
+++     int res;
+++
+++     count /= sf_get_frame_size(ip_data->sf);
+++
+++     while (count) {
+++             if (priv->swr_frame->nb_samples == 0) {
+++                     res = ffmpeg_get_frame(priv);
+++                     if (res == AVERROR_EOF)
+++                             break;
+++                     else if (res == 0)
+++                             continue;
+++                     else if (res < 0)
+++                             goto err;
+++
+++                     res = ffmpeg_convert_frame(priv);
+++                     if (res < 0)
+++                             goto err;
+++             }
+++
+++             int copy_frames = min_i(count, priv->swr_frame->nb_samples);
+++             int copy_bytes = copy_frames * sf_get_frame_size(ip_data->sf);
+++             void *dst = priv->swr_frame->extended_data[0] + priv->swr_frame_start;
+++             memcpy(buffer + written, dst, copy_bytes);
+++
+++             priv->swr_frame->nb_samples -= copy_frames;
+++             priv->swr_frame_start += copy_bytes;
+++             count -= copy_frames;
+++             written += copy_bytes;
++      }
++-     out_size = min_i(output->buffer_used_len, count);
++-     memcpy(buffer, output->buffer_pos, out_size);
++-     output->buffer_used_len -= out_size;
++-     output->buffer_pos += out_size;
++-     return out_size;
+++     return written;
+++err:
+++     d_print("%s\n", ffmpeg_errmsg(res));
+++     return -IP_ERROR_INTERNAL;
++ }
++ 
++ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++-     AVStream *st = priv->input_context->streams[priv->input->stream_index];
++-     int ret;
+++     AVStream *st = priv->format_ctx->streams[priv->stream_index];
++ 
++-     priv->input->seek_ts = offset * AV_TIME_BASE;
++-     priv->input->prev_frame_end = -1;
+++     priv->seek_ts = offset * AV_TIME_BASE;
+++     priv->prev_frame_end = -1;
++      int64_t ts = av_rescale(offset, st->time_base.den, st->time_base.num);
++ 
++-     avcodec_flush_buffers(priv->codec_context);
++-     /* TODO: also flush swresample buffers */
++-     /* Force reading a new packet in next ffmpeg_fill_buffer(). */
++-     priv->input->curr_pkt_size = 0;
++-
++-     ret = avformat_seek_file(priv->input_context,
++-                     priv->input->stream_index, 0, ts, ts, 0);
++-
++-     if (ret < 0) {
+++     int ret = avformat_seek_file(priv->format_ctx,
+++                     priv->stream_index, 0, ts, ts, 0);
+++     if (ret < 0)
++              return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++-     } else {
++-             ffmpeg_buffer_flush(priv->output);
++-             return 0;
++-     }
+++
+++     priv->swr_frame->nb_samples = 0;
+++     avcodec_flush_buffers(priv->codec_ctx);
+++     /* also flush swresample buffers? */
+++     return 0;
++ }
++ 
++ static void ffmpeg_read_metadata(struct growing_keyvals *c, AVDictionary *metadata)
++@@ -445,7 +462,7 @@ static int ffmpeg_read_comments(struct input_plugin_data *ip_data,
++              struct keyval **comments)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++-     AVFormatContext *ic = priv->input_context;
+++     AVFormatContext *ic = priv->format_ctx;
++ 
++      GROWING_KEYVALS(c);
++ 
++@@ -463,29 +480,29 @@ static int ffmpeg_read_comments(struct input_plugin_data *ip_data,
++ static int ffmpeg_duration(struct input_plugin_data *ip_data)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++-     return priv->input_context->duration / AV_TIME_BASE;
+++     return priv->format_ctx->duration / AV_TIME_BASE;
++ }
++ 
++ static long ffmpeg_bitrate(struct input_plugin_data *ip_data)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++-     long bitrate = priv->input_context->bit_rate;
+++     long bitrate = priv->format_ctx->bit_rate;
++      return bitrate ? bitrate : -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++ }
++ 
++ static long ffmpeg_current_bitrate(struct input_plugin_data *ip_data)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++-     AVStream *st = priv->input_context->streams[priv->input->stream_index];
+++     AVStream *st = priv->format_ctx->streams[priv->stream_index];
++      long bitrate = -1;
++      /* ape codec returns silly numbers */
++      if (priv->codec->id == AV_CODEC_ID_APE)
++              return -1;
++-     if (priv->input->curr_duration > 0) {
++-             double seconds = priv->input->curr_duration * av_q2d(st->time_base);
++-             bitrate = (8 * priv->input->curr_size) / seconds;
++-             priv->input->curr_size = 0;
++-             priv->input->curr_duration = 0;
+++     if (priv->curr_duration > 0) {
+++             double seconds = priv->curr_duration * av_q2d(st->time_base);
+++             bitrate = (8 * priv->curr_size) / seconds;
+++             priv->curr_size = 0;
+++             priv->curr_duration = 0;
++      }
++      return bitrate;
++ }
++@@ -500,7 +517,7 @@ static char *ffmpeg_codec_profile(struct input_plugin_data *ip_data)
++ {
++      struct ffmpeg_private *priv = ip_data->private;
++      const char *profile;
++-     profile = av_get_profile_name(priv->codec, priv->codec_context->profile);
+++     profile = av_get_profile_name(priv->codec, priv->codec_ctx->profile);
++      return profile ? xstrdup(profile) : NULL;
++ }
++ 
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..aad27c8d6db97442fabdb09b98c53505105f2325
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,31 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 14:28:46 +0300
++Subject: Validate sample format in ip_open()
++
++To prevent segfault in ip_setup() because channels=0, validate ip_data->sf
++after opening ip.
++---
++ input.c | 10 ++++++++++
++ 1 file changed, 10 insertions(+)
++
++diff --git a/input.c b/input.c
++index c20cb3f..f5c5b3c 100644
++--- a/input.c
+++++ b/input.c
++@@ -605,6 +605,16 @@ int ip_open(struct input_plugin *ip)
++              ip_reset(ip, 1);
++              return rc;
++      }
+++
+++     unsigned bits = sf_get_bits(ip->data.sf);
+++     unsigned channels = sf_get_channels(ip->data.sf);
+++     unsigned rate = sf_get_rate(ip->data.sf);
+++     if (!bits || !channels || !rate) {
+++             d_print("corrupt file: bits = %u, channels = %u, rate = %u\n",
+++                             bits, channels, rate);
+++             return -IP_ERROR_FILE_FORMAT;
+++     }
+++
++      ip->open = 1;
++      return 0;
++ }
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..89f2cf9762e67a4664cd4f3b227c4c9f305ba9ed
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,21 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 14:53:52 +0300
++Subject: ip/ffmpeg: flush swresample buffer when seeking
++
++---
++ ip/ffmpeg.c | 2 +-
++ 1 file changed, 1 insertion(+), 1 deletion(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index 42f630e..775e7de 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -444,7 +444,7 @@ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
++ 
++      priv->swr_frame->nb_samples = 0;
++      avcodec_flush_buffers(priv->codec_ctx);
++-     /* also flush swresample buffers? */
+++     swr_convert(priv->swr, NULL, 0, NULL, 0); /* flush swr buffer */
++      return 0;
++ }
++ 
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e70915336c769f6437e1278ffb9e2d3678e45e60
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,38 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 15:02:34 +0300
++Subject: ip/ffmpeg: remember swr_frame's capacity
++
++---
++ ip/ffmpeg.c | 5 +++--
++ 1 file changed, 3 insertions(+), 2 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index 775e7de..c659c13 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -49,6 +49,7 @@ struct ffmpeg_private {
++ 
++      /* A buffer to hold swr_convert()-ed samples */
++      AVFrame *swr_frame;
+++     int swr_frame_samples_cap;
++      int swr_frame_start;
++ 
++      /* Bitrate estimation */
++@@ -213,6 +214,7 @@ static int ffmpeg_init_swr_frame(struct ffmpeg_private *priv,
++              d_print("av_frame_get_buffer(): %s\n", ffmpeg_errmsg(res));
++              return -IP_ERROR_INTERNAL;
++      }
+++     priv->swr_frame_samples_cap = frame->nb_samples;
++      frame->nb_samples = 0;
++ 
++      priv->swr_frame = frame;
++@@ -378,8 +380,7 @@ static int ffmpeg_convert_frame(struct ffmpeg_private *priv)
++ {
++      int res = swr_convert(priv->swr,
++                      priv->swr_frame->extended_data,
++-                     /* TODO: proper buffer capacity */
++-                     priv->frame->nb_samples,
+++                     priv->swr_frame_samples_cap,
++                      (const uint8_t **)priv->frame->extended_data,
++                      priv->frame->nb_samples);
++      if (res >= 0) {
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fd72b0f693b162ecdf1a2ed335afb91d190412ca
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,20 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 15:54:19 +0300
++Subject: ip/ffmpeg: reset swr_frame_start when seeking
++
++---
++ ip/ffmpeg.c | 1 +
++ 1 file changed, 1 insertion(+)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index c659c13..71cc511 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -444,6 +444,7 @@ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
++              return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++ 
++      priv->swr_frame->nb_samples = 0;
+++     priv->swr_frame_start = 0;
++      avcodec_flush_buffers(priv->codec_ctx);
++      swr_convert(priv->swr, NULL, 0, NULL, 0); /* flush swr buffer */
++      return 0;
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cf01f63efb892bf06ad669fa06a38ca8ac4d9d4d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,151 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 17:27:20 +0300
++Subject: ip/ffmpeg: better frame skipping logic
++
++---
++ ip/ffmpeg.c | 82 ++++++++++++++++++++++++++++++-------------------------------
++ 1 file changed, 41 insertions(+), 41 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index 71cc511..af6ecfb 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -44,8 +44,8 @@ struct ffmpeg_private {
++ 
++      AVPacket *pkt;
++      AVFrame *frame;
++-     int64_t seek_ts;
++-     int64_t prev_frame_end;
+++     double seek_ts;
+++     int64_t skip_samples;
++ 
++      /* A buffer to hold swr_convert()-ed samples */
++      AVFrame *swr_frame;
++@@ -249,7 +249,6 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
++      priv.pkt = av_packet_alloc();
++      priv.frame = av_frame_alloc();
++      priv.seek_ts = -1;
++-     priv.prev_frame_end = -1;
++ 
++      priv.swr = swr_alloc();
++      ffmpeg_set_sf_and_swr_opts(priv.swr, priv.codec_ctx,
++@@ -283,37 +282,37 @@ static int ffmpeg_close(struct input_plugin_data *ip_data)
++      return 0;
++ }
++ 
++-/*
++- * return:
++- *    0 - retry
++- *   >0 - ok
++- */
++-static int ffmpeg_seek_into_frame(struct ffmpeg_private *priv, int64_t frame_ts)
+++static int64_t ffmpeg_calc_skip_samples(struct ffmpeg_private *priv)
++ {
++-     if (frame_ts >= 0) {
++-             AVStream *s = priv->format_ctx->streams[priv->stream_index];
++-             frame_ts = av_rescale_q(frame_ts, s->time_base, AV_TIME_BASE_Q);
+++     int64_t ts;
+++     if (priv->frame->pts >= 0) {
+++             ts = priv->frame->pts;
+++     } else if (priv->frame->pkt_dts >= 0) {
+++             ts = priv->frame->pkt_dts;
++      } else {
++-             frame_ts = priv->prev_frame_end;
+++             d_print("AVFrame.pts and AVFrame.pkt_dts are unset\n");
+++             return -1;
++      }
++ 
++-     if (frame_ts >= priv->seek_ts)
++-             return 1;
++-
++-     int64_t frame_dur = av_rescale(priv->frame->nb_samples,
++-                     AV_TIME_BASE, priv->frame->sample_rate);
++-     int64_t frame_end = frame_ts + frame_dur;
++-     priv->prev_frame_end = frame_end;
+++     AVStream *s = priv->format_ctx->streams[priv->stream_index];
+++     double frame_ts = ts * av_q2d(s->time_base);
++ 
++-     d_print("seek_ts: %ld, frame_ts: %ld, frame_end: %ld\n",
++-                     priv->seek_ts, frame_ts, frame_end);
+++     d_print("seek_ts: %.6fs, frame_ts: %.6fs\n", priv->seek_ts, frame_ts);
++ 
++-     if (frame_end <= priv->seek_ts)
+++     if (frame_ts >= priv->seek_ts)
++              return 0;
+++     return (priv->seek_ts - frame_ts) * priv->frame->sample_rate;
+++}
++ 
++-     int64_t skip_samples = av_rescale(priv->seek_ts - frame_ts,
++-                     priv->frame->sample_rate, AV_TIME_BASE);
++-     priv->frame->nb_samples -= skip_samples;
+++static void ffmpeg_skip_frame_part(struct ffmpeg_private *priv)
+++{
+++     if (priv->skip_samples >= priv->frame->nb_samples) {
+++             d_print("skipping frame: %d samples\n",
+++                             priv->frame->nb_samples);
+++             priv->skip_samples -= priv->frame->nb_samples;
+++             priv->frame->nb_samples = 0;
+++             return;
+++     }
++ 
++      int bps = av_get_bytes_per_sample(priv->frame->format);
++ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 24, 100)
++@@ -322,15 +321,17 @@ static int ffmpeg_seek_into_frame(struct ffmpeg_private *priv, int64_t frame_ts)
++      int channels = priv->codec_ctx->channels;
++ #endif
++ 
+++     priv->frame->nb_samples -= priv->skip_samples;
+++
++      /* Just modify frame's data pointer because it's throw-away */
++      if (av_sample_fmt_is_planar(priv->frame->format)) {
++              for (int i = 0; i < channels; i++)
++-                     priv->frame->extended_data[i] += skip_samples * bps;
+++                     priv->frame->extended_data[i] += priv->skip_samples * bps;
++      } else {
++-             priv->frame->extended_data[0] += skip_samples * channels * bps;
+++             priv->frame->extended_data[0] += priv->skip_samples * channels * bps;
++      }
++-     d_print("skipping %ld samples\n", skip_samples);
++-     return 1;
+++     d_print("skipping %ld samples\n", priv->skip_samples);
+++     priv->skip_samples = 0;
++ }
++ 
++ /*
++@@ -361,17 +362,16 @@ static int ffmpeg_get_frame(struct ffmpeg_private *priv)
++      if (res < 0)
++              return res;
++ 
++-     int64_t frame_ts = -1;
++-     if (priv->frame->pts >= 0)
++-             frame_ts = priv->frame->pts;
++-     else if (priv->frame->pkt_dts >= 0)
++-             frame_ts = priv->frame->pkt_dts;
+++     if (priv->seek_ts > 0) {
+++             priv->skip_samples = ffmpeg_calc_skip_samples(priv);
+++             if (priv->skip_samples >= 0)
+++                     priv->seek_ts = -1;
+++     }
++ 
++-     if (priv->seek_ts > 0 && (frame_ts >= 0 || priv->prev_frame_end >= 0)) {
++-             if (ffmpeg_seek_into_frame(priv, frame_ts) == 0)
+++     if (priv->skip_samples > 0) {
+++             ffmpeg_skip_frame_part(priv);
+++             if (priv->frame->nb_samples == 0)
++                      return 0;
++-             priv->seek_ts = -1;
++-             priv->prev_frame_end = -1;
++      }
++      return 1;
++ }
++@@ -434,8 +434,8 @@ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
++      struct ffmpeg_private *priv = ip_data->private;
++      AVStream *st = priv->format_ctx->streams[priv->stream_index];
++ 
++-     priv->seek_ts = offset * AV_TIME_BASE;
++-     priv->prev_frame_end = -1;
+++     priv->seek_ts = offset;
+++     priv->skip_samples = 0;
++      int64_t ts = av_rescale(offset, st->time_base.den, st->time_base.num);
++ 
++      int ret = avformat_seek_file(priv->format_ctx,
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a52c31cb916df4bf0d118285ecd98faa1402b371
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,21 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 17 Aug 2025 19:22:50 +0300
++Subject: ip/ffmpeg: don't process empty frames
++
++---
++ ip/ffmpeg.c | 2 +-
++ 1 file changed, 1 insertion(+), 1 deletion(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index af6ecfb..dd9061a 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -356,7 +356,7 @@ static int ffmpeg_get_frame(struct ffmpeg_private *priv)
++              priv->curr_duration += priv->pkt->duration;
++ 
++              res = avcodec_send_packet(priv->codec_ctx, priv->pkt);
++-             if (res == AVERROR(EAGAIN))
+++             if (res == 0 || res == AVERROR(EAGAIN))
++                      return 0;
++      }
++      if (res < 0)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cdad99ce760d0792fef079653cd95449280417dd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,111 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Mon, 18 Aug 2025 03:32:22 +0300
++Subject: ip/ffmpeg: improve readability
++
++Previously ffmpeg_read()'s while loop was kinda leaking into
++ffmpeg_get_frame(), now it doesn't.
++---
++ ip/ffmpeg.c | 36 ++++++++++++++++++++----------------
++ 1 file changed, 20 insertions(+), 16 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index dd9061a..fc74895 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -337,30 +337,32 @@ static void ffmpeg_skip_frame_part(struct ffmpeg_private *priv)
++ /*
++  * return:
++  *   <0 - error
++- *    0 - retry
+++ *    0 - eof
++  *   >0 - ok
++  */
++ static int ffmpeg_get_frame(struct ffmpeg_private *priv)
++ {
++-     int res = avcodec_receive_frame(priv->codec_ctx, priv->frame);
+++     int res;
+++retry:
+++     res = avcodec_receive_frame(priv->codec_ctx, priv->frame);
++      if (res == AVERROR(EAGAIN)) {
++              av_packet_unref(priv->pkt);
++              res = av_read_frame(priv->format_ctx, priv->pkt);
++              if (res < 0)
++-                     return res;
+++                     goto err;
++ 
++              if (priv->pkt->stream_index != priv->stream_index)
++-                     return 0;
+++                     goto retry;
++ 
++              priv->curr_size += priv->pkt->size;
++              priv->curr_duration += priv->pkt->duration;
++ 
++              res = avcodec_send_packet(priv->codec_ctx, priv->pkt);
++              if (res == 0 || res == AVERROR(EAGAIN))
++-                     return 0;
+++                     goto retry;
++      }
++      if (res < 0)
++-             return res;
+++             goto err;
++ 
++      if (priv->seek_ts > 0) {
++              priv->skip_samples = ffmpeg_calc_skip_samples(priv);
++@@ -371,9 +373,14 @@ static int ffmpeg_get_frame(struct ffmpeg_private *priv)
++      if (priv->skip_samples > 0) {
++              ffmpeg_skip_frame_part(priv);
++              if (priv->frame->nb_samples == 0)
++-                     return 0;
+++                     goto retry;
++      }
++      return 1;
+++err:
+++     if (res == AVERROR_EOF)
+++             return 0;
+++     d_print("%s\n", ffmpeg_errmsg(res));
+++     return -IP_ERROR_INTERNAL;
++ }
++ 
++ static int ffmpeg_convert_frame(struct ffmpeg_private *priv)
++@@ -386,8 +393,10 @@ static int ffmpeg_convert_frame(struct ffmpeg_private *priv)
++      if (res >= 0) {
++              priv->swr_frame->nb_samples = res;
++              priv->swr_frame_start = 0;
+++             return res;
++      }
++-     return res;
+++     d_print("%s\n", ffmpeg_errmsg(res));
+++     return -IP_ERROR_INTERNAL;
++ }
++ 
++ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int count)
++@@ -401,16 +410,14 @@ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int coun
++      while (count) {
++              if (priv->swr_frame->nb_samples == 0) {
++                      res = ffmpeg_get_frame(priv);
++-                     if (res == AVERROR_EOF)
+++                     if (res == 0)
++                              break;
++-                     else if (res == 0)
++-                             continue;
++                      else if (res < 0)
++-                             goto err;
+++                             return res;
++ 
++                      res = ffmpeg_convert_frame(priv);
++                      if (res < 0)
++-                             goto err;
+++                             return res;
++              }
++ 
++              int copy_frames = min_i(count, priv->swr_frame->nb_samples);
++@@ -424,9 +431,6 @@ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int coun
++              written += copy_bytes;
++      }
++      return written;
++-err:
++-     d_print("%s\n", ffmpeg_errmsg(res));
++-     return -IP_ERROR_INTERNAL;
++ }
++ 
++ static int ffmpeg_seek(struct input_plugin_data *ip_data, double offset)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..99bd8457cc6a208f9d5c543ae0586d9d3a6b9181
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,24 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Sun, 24 Aug 2025 19:16:57 +0300
++Subject: ip/ffmpeg: fix building for ffmpeg 8.0
++
++avcodec_close() can be safely removed because avcodec_free_context()
++is its replacement since 2016. See ffmpeg commit 2ef6dab0a79
++
++Builds with v3.3.9 v4.0.6 v6.1.3 v7.1.1 v8.0
++---
++ ip/ffmpeg.c | 1 -
++ 1 file changed, 1 deletion(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index fc74895..2cb0767 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -223,7 +223,6 @@ static int ffmpeg_init_swr_frame(struct ffmpeg_private *priv,
++ 
++ static void ffmpeg_free(struct ffmpeg_private *priv)
++ {
++-     avcodec_close(priv->codec_ctx);
++      avcodec_free_context(&priv->codec_ctx);
++      avformat_close_input(&priv->format_ctx);
++ 
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..52352120c6cc3638cf723cfc0883b301d3653f4a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,30 @@@
++From: ihy123 <aladinandreyy@gmail.com>
++Date: Mon, 25 Aug 2025 11:17:06 +0300
++Subject: ip/ffmpeg: change sample format conversions
++
++---
++ ip/ffmpeg.c | 10 ++++------
++ 1 file changed, 4 insertions(+), 6 deletions(-)
++
++diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
++index 2cb0767..2d3c610 100644
++--- a/ip/ffmpeg.c
+++++ b/ip/ffmpeg.c
++@@ -157,13 +157,11 @@ static void ffmpeg_set_sf_and_swr_opts(SwrContext *swr, AVCodecContext *cc,
++      av_opt_set_int(swr, "in_sample_rate", cc->sample_rate, 0);
++      av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0);
++ 
++-     *out_sample_fmt = cc->sample_fmt;
++-     switch (*out_sample_fmt) {
++-             case AV_SAMPLE_FMT_U8:
++-                     sf |= sf_bits(8) | sf_signed(0);
++-                     break;
++-             case AV_SAMPLE_FMT_S32:
+++     switch (cc->sample_fmt) {
+++             case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLTP:
+++             case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32P:
++                      sf |= sf_bits(32) | sf_signed(1);
+++                     *out_sample_fmt = AV_SAMPLE_FMT_S32;
++                      break;
++              default:
++                      sf |= sf_bits(16) | sf_signed(1);
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c78695c405d275742ff21c520ef86145e40aeacd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++0001-atomic_ld.patch
++0002-fix-blhc.patch
++0003-ip-ffmpeg-more-precise-seeking.patch
++0004-ip-ffmpeg-skip-samples-only-when-needed.patch
++0005-ip-ffmpeg-remove-excessive-version-checks.patch
++0006-ip-ffmpeg-major-refactor.patch
++0007-Validate-sample-format-in-ip_open.patch
++0008-ip-ffmpeg-flush-swresample-buffer-when-seeking.patch
++0009-ip-ffmpeg-remember-swr_frame-s-capacity.patch
++0010-ip-ffmpeg-reset-swr_frame_start-when-seeking.patch
++0011-ip-ffmpeg-better-frame-skipping-logic.patch
++0012-ip-ffmpeg-don-t-process-empty-frames.patch
++0013-ip-ffmpeg-improve-readability.patch
++0014-ip-ffmpeg-fix-building-for-ffmpeg-8.0.patch
++0015-ip-ffmpeg-change-sample-format-conversions.patch
diff --cc debian/rules
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..765979d827fa86dfb4940fa0d0ce3471788f7db1
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,59 @@@
++#!/usr/bin/make -f
++# -*- makefile -*-
++
++include /usr/share/dpkg/architecture.mk
++ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH))
++CROSS = CROSS=$(DEB_HOST_GNU_TYPE)- PKG_CONFIG=$(DEB_HOST_GNU_TYPE)-pkg-config
++endif
++
++# The following architectures need the -latomic flag
++# to build, otherwise we FTBFS with
++#    ./track_info.c:47: undefined reference to `__atomic_fetch_add_8'
++# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=935678
++# Depends on 13-atomic_ld.patch
++ifneq (,$(findstring $(DEB_HOST_ARCH), armel m68k mipsel powerpc sh4))
++export LDLIBS += -latomic
++endif
++
++DEB_CFLAGS_MAINT_APPEND  += -I/usr/include/ncursesw
++DEB_BUILD_MAINT_OPTIONS   = hardening=+all
++DPKG_EXPORT_BUILDFLAGS    = 1
++include /usr/share/dpkg/buildflags.mk
++
++suggested_deps = pulse jack
++
++EXTRA_CMUS_DIR_OP_PLUGINS = debian/cmus/usr/lib/cmus/op/
++EXTRA_CMUS_PLUGINS := $(foreach plugin,$(suggested_deps),$(plugin).so)
++
++%:
++      dh $@ --with bash-completion
++
++override_dh_auto_configure:
++      $(CROSS) ./configure \
++              prefix=/usr \
++              CONFIG_ARTS=n \
++              CONFIG_ROAR=n \
++              DEBUG=0
++
++override_dh_auto_build:
++      # Pass V=2 to make to enable verbose build logs, which is useful for
++      # porters, sorting out build hardening issues, etc.
++      dh_auto_build -- V=2
++
++override_dh_install:
++      dh_install -pcmus
++      dh_movefiles -pcmus-plugin-ffmpeg --sourcedir=debian/cmus/ \
++              /usr/lib/cmus/ip/ffmpeg.so
++
++override_dh_installdocs:
++      dh_installdocs
++      # do not install zsh and bash completion twice
++      rm debian/cmus/usr/share/doc/cmus/contrib/_cmus \
++              debian/cmus/usr/share/doc/cmus/contrib/cmus.bash-completion
++
++override_dh_shlibdeps:
++      dh_shlibdeps -pcmus $(foreach plugin,$(EXTRA_CMUS_PLUGINS),-X$(plugin))
++      dpkg-shlibdeps -O -dSuggests \
++              $(foreach plugin,$(EXTRA_CMUS_PLUGINS),$(EXTRA_CMUS_DIR_OP_PLUGINS)$(plugin)) \
++              >> debian/cmus.substvars
++      dh_shlibdeps --remaining-packages
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8424db446e1abcdef8338ebc449ccd27996ac11f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++---
++include:
++  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..163aaf8d82b6c54f23c45f32895dbdfdcc27b047
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++3.0 (quilt)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7d5f13de201dc7e152a3bbbf286648ee728e9735
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Bug-Database: https://github.com/cmus/cmus/issues
++Bug-Submit: https://github.com/cmus/cmus/issues/new
++Repository: https://github.com/cmus/cmus.git
++Repository-Browse: https://github.com/cmus/cmus
diff --cc debian/watch
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dca9c327d373e055484af3a1b73091ff66fbf884
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++version=4
++opts="dversionmangle=s/\+git\d+$//,uversionmangle=s/([\d\.]+)-(rc|beta)(.*)/\1~\2\3/,filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/cmus-$1\.tar\.gz/" \
++https://github.com/cmus/cmus/tags .*/v?(\d\S*)\.tar\.gz